TypeScript The satisfies Operator
The satisfies operator checks a value against a type without replacing the inferred type of the value. The check is as strict as an annotation, and the exact literal types survive it.
Annotation widens, satisfies keeps
The annotated constant widens its mode member to the whole ModeName union. The checked constant keeps the literal light, and the assignment to the literal type proves it.
type ModeName = 'light' | 'dark' | 'auto';
interface ButtonStyle {
mode: ModeName;
size: string;
}
const annotated: ButtonStyle = { mode: 'light', size: 'small' };
const checked = { mode: 'light', size: 'small' } satisfies ButtonStyle;
const keptMode: 'light' = checked.mode;
const widened: ModeName = annotated.mode;
console.log(keptMode);
console.log(widened);A typo in a config key is refused
The config writes prot where the type declares port. satisfies applies the excess property check and refuses the object.
interface AppConfig {
host: string;
port: number;
}
const cfg = {
host: 'localhost',
prot: 8080,
} satisfies AppConfig;
console.log(cfg.host);A config keeps its exact values
The server config passes the satisfies check against its interface. Its host and port members keep their literal types for later code.
type HostName = 'api.local' | 'api.dev';
type PortNumber = 8080 | 3000;
interface ServerConfig {
host: HostName;
port: PortNumber;
retries: number;
}
const serverCfg = {
host: 'api.local',
port: 8080,
retries: 3,
} satisfies ServerConfig;
const exactPort: 8080 = serverCfg.port;
const exactHost: 'api.local' = serverCfg.host;
console.log(exactHost);
console.log(exactPort);Example
type ColorName = 'red' | 'green' | 'blue';
interface ThemeConfig {
colors: Record<ColorName, string>;
dark: boolean;
}
const theme = {
colors: { red: '#f00', green: '#0f0', blue: '#00f' },
dark: true,
} satisfies ThemeConfig;
console.log(theme.colors.green);
console.log(theme.dark);Key points
- satisfies checks a value against a type and keeps the inferred type of the value.
- A type annotation replaces the inferred type with the wider annotated type.
- Literal members stay literal under satisfies, so later code can rely on the exact values.
- satisfies still refuses excess properties and members with the wrong type.
- A config object gains typo protection while its exact values stay available as literals.
In this example, satisfies proves the theme matches the config shape, including every color key, while the theme keeps its own precise inferred type.
Try it Yourself
Edit the code, then press Run.
Running is simulated ยท TypeScript Playground
Exercise
How does satisfies differ from a plain type annotation on the same value?