Over the past six years, I’ve worked with TypeScript and witnessed its evolution, incorporating many powerful features. One operator that significantly improved type checking in my projects is the satisfies operator introduced in TypeScript 4.9.
This operator has been a game-changer for ensuring type correctness while preserving type information.
In this article, we will learn about what the satisfies operator does and how it can help you write more robust TypeScript code.
What is the ‘satisfies’ Operator?
The satisfies operator validates that a value matches a specific type without changing the type of the expression. It sits between a value and a type, checking if the value conforms to that type while preserving the value’s original, more specific type information.
It’s like telling TypeScript: “Make sure this value matches this type, but don’t forget what the actual value is.”
Why We Need the ‘satisfies’ Operator in TypeScript
Before diving into examples, let’s understand why we needed this operator in the first place.
Problem: Type Widening vs. Type Validation
In TypeScript, we often face a dilemma:
- We want to validate that a value matches a specific type
- We also want to retain the value’s precise type information
Before satisfies, we had to choose one or the other, which led to compromises in type safety or developer experience.
How to Use the ‘satisfies’ Operator
Let’s explore practical examples of how to use this operator effectively.
Method 1: Validating Object Literals While Preserving Property Types
type RGB = {
red: number;
green: number;
blue: number;
};
type HSL = {
hue: number;
saturation: number;
lightness: number;
};
type ColorFormat = RGB | HSL;
// Using 'satisfies' to validate while preserving specific types
const color = {
red: 255,
green: 0,
blue: 128
} satisfies ColorFormat;
// We can access 'red' property because TypeScript knows it exists
console.log(color.red); // Works fine!
In this example, the satisfies operator ensures our object conforms to the ColorFormat type, but TypeScript still knows exactly which properties exist.

Method 2: Working with String Literal Types in TypeScript
Let’s say we’re building a U.S. state selection component:
type USState = 'AL' | 'AK' | 'AZ' | /* ...other states */ 'WY';
const stateData = {
'NY': { name: 'New York', population: 19.45, capital: 'Albany' },
'CA': { name: 'California', population: 39.51, capital: 'Sacramento' },
'TX': { name: 'Texas', population: 29.15, capital: 'Austin' }
} satisfies Record<USState, { name: string, population: number, capital: string }>;
// TypeScript knows exactly which states we have
const californiaPopulation = stateData.CA.population; // Works!
The satisfies operator ensures we only use valid state codes while preserving the exact keys we’ve defined.

Method 3: Validating Configurations in TypeScript
When working with configuration objects, the satisfies operator is extremely valuable:
// types.ts
type ApiEndpoint = 'users' | 'posts' | 'comments';
type ApiConfig = {
[key in ApiEndpoint]?: {
url: string;
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
needsAuth: boolean;
[extra: string]: any; // allows additional properties like cache
};
};
// apiConfig.ts
const apiConfig = {
users: {
url: 'https://jsonplaceholder.typicode.com/users',
method: 'GET',
needsAuth: false
},
posts: {
url: 'https://jsonplaceholder.typicode.com/posts',
method: 'GET',
needsAuth: false,
cache: true
},
comments: {
url: 'https://jsonplaceholder.typicode.com/comments',
method: 'GET',
needsAuth: false
}
} satisfies ApiConfig;
// callApi.ts
async function callApi(endpoint: ApiEndpoint): Promise<void> {
const config = apiConfig[endpoint];
if (!config) {
console.error(`No config found for endpoint: ${endpoint}`);
return;
}
console.debug(`Calling ${endpoint} with config:`, config);
try {
const response = await fetch(config.url, {
method: config.method,
headers: config.needsAuth
? { Authorization: 'Bearer YOUR_TOKEN' }
: {}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
console.log(` Response from ${endpoint}:`, data.slice(0, 2)); // Show 2 records for preview
} catch (error) {
console.error(` Failed to fetch ${endpoint}:`, error);
}
}
// main.ts (Execution)
(async () => {
await callApi('users');
await callApi('posts');
await callApi('comments');
})();
The satisfies operator catches the extra cache property, ensuring our configuration strictly adheres to our API contract.

‘satisfies’ vs Type Assertions in TypeScript
You might wonder how satisfies. It differs from type assertions using as
. Here’s a key comparison:
// Using 'as' (type assertion)
const colorAs = {
red: 255,
green: 0,
blue: 128,
alpha: 0.5 // No error!
} as RGB;
// Using 'satisfies'
const colorSatisfies = {
red: 255,
green: 0,
blue: 128,
alpha: 0.5 // Error: Object literal may only specify known properties
} satisfies RGB;
Type assertions with as silence TypeScript, potentially hiding errors. The satisfies operator validates without compromising, catching mistakes like the extra alpha property.

Real-World Example in TypeScript: Form Validation in a U.S. Tax Filing Application
Let’s look at how satisfies can help with a tax filing application:
type TaxFormField =
| 'ssn'
| 'filingStatus'
| 'dependents'
| 'income'
| 'deductions';
type FieldValidation = {
required: boolean;
validate: (value: any) => boolean;
errorMessage: string;
};
const formValidations = {
ssn: {
required: true,
validate: (value: string) => /^\d{3}-\d{2}-\d{4}$/.test(value),
errorMessage: 'Please enter a valid SSN (e.g., 123-45-6789)'
},
filingStatus: {
required: true,
validate: (value: string) => ['single', 'married', 'headOfHousehold'].includes(value),
errorMessage: 'Please select a valid filing status'
},
income: {
required: true,
validate: (value: number) => value >= 0,
errorMessage: 'Income must be a positive number'
}
} satisfies Partial<Record<TaxFormField, FieldValidation>>;
// TypeScript knows the exact fields and their types
const validateSsn = formValidations.ssn.validate;
The satisfies operator ensures we only use valid form field names while preserving the specific validation functions for each field.

When to Use the ‘satisfies’ Operator
Based on my experience, I recommend using the satisfies operator when:
- You need to validate that a value conforms to a type, but want to keep its specific properties accessible
- You’re working with literal types and want to preserve the exact literals
- You want to catch errors in object literals without sacrificing type information
- You’re defining configurations that must adhere to a schema
The satisfies operator has become an essential part of my TypeScript toolkit, especially for larger projects where type safety is crucial.
By using this operator effectively, you can improve both type safety and developer experience in your TypeScript projects. It provides validation without the compromise of type assertions, giving you the best of both worlds.
If you’re looking to write more robust TypeScript code, I highly recommend incorporating the satisfies operator into your development practices.
You may like to read:
- TypeScript let vs var Difference
- Type vs Interface in TypeScript
- TypeScript: Check If a Key Exists in a Object

I am Bijay Kumar, a Microsoft MVP in SharePoint. Apart from SharePoint, I started working on Python, Machine learning, and artificial intelligence for the last 5 years. During this time I got expertise in various Python libraries also like Tkinter, Pandas, NumPy, Turtle, Django, Matplotlib, Tensorflow, Scipy, Scikit-Learn, etc… for various clients in the United States, Canada, the United Kingdom, Australia, New Zealand, etc. Check out my profile.