Satisfies
Introduced in TypeScript 4.9, the satisfies operator fixes a major flaw with explicit type annotations: the loss of literal type information.
The problem with explicit annotations
When you explicitly annotate a variable, TypeScript widens the assigned value to exactly match that annotation.
type Colors = Record<string, string | number[]>;
const theme: Colors = {
primary: "blue",
secondary: [255, 0, 0]
};
// Error: Property 'toUpperCase' does not exist on type 'string | number[]'
// theme.primary.toUpperCase();
Because theme is annotated as Colors, TypeScript forgets that primary was specifically a string and secondary was an array. It only knows they are string | number[].
The solution: satisfies
The satisfies operator allows you to validate that an object matches a shape, without widening its inferred literal types.
const safeTheme = {
primary: "blue",
secondary: [255, 0, 0]
} satisfies Colors;
// Valid! TS remembers this is a string
safeTheme.primary.toUpperCase();
// Valid! TS remembers this is an array
safeTheme.secondary.push(0);
When to use satisfies
Use satisfies primarily for configuration objects, theme definitions, or route maps. Anywhere you want to guarantee that a massive object conforms to a strict interface, but you still want the precise autocomplete and literal type inference of its exact values.
satisfiesvalidates that a value matches a type, but preserves the most specific inferred type of the value instead of widening it to the interface.