Use TypeScript satisfies to Validate Object Literals While Preserving Literal Types
Use TypeScript satisfies to validate object literals against a type while preserving exact literal property types for autocompletion.
04 May 2026, 14:31 UTC

Desired outcome
You have an object literal and a TypeScript type that describes its shape. You want the compiler to reject mismatched property types, but you also want the object's properties to keep their exact literal types—for example, 'dark' instead of string—so editor autocompletion and narrowed checks keep working.
Use the satisfies operator. It validates that a value is assignable to a type without changing the value's inferred type. It is available in TypeScript 4.9 and later and is erased when the code is compiled.
Prerequisites
- TypeScript 4.9 or later installed in the project.
- A TypeScript configuration file (tsconfig.json) or the ability to run tsc against a .ts file.
- An editor with TypeScript language services is helpful but not required.
Check the TypeScript version
Run this command in the project root. No special permissions are required.
npx tsc --version
Expected output: a version number such as 4.9.5 or later. If the reported version is earlier than 4.9, satisfies is a syntax error. Upgrade TypeScript before continuing.
Risk: none. This command only reads the compiler version.
Declare the target type
type ThemeConfig = {
primary: string;
mode: 'light' | 'dark';
};
Apply satisfies to an object literal
const theme = {
primary: '#0066ff',
mode: 'dark',
} satisfies ThemeConfig;
The object literal is checked against ThemeConfig. If you change mode to 'bright', tsc --noEmit reports an error because 'bright' is not assignable to 'light' | 'dark'. The variable theme keeps the inferred type { primary: string; mode: "dark" }, so theme.mode remains the literal type "dark" rather than being widened to string.
Comparison with alternatives
| Approach | Rejects incompatible types | Preserves literal types | Notes |
|---|---|---|---|
| Type annotation: const theme: ThemeConfig = { ... } | Yes | No | Variable type is ThemeConfig; literal properties widen to string. |
| Type assertion: const theme = { ... } as ThemeConfig | No | Yes | Suppresses incompatible-type errors and can hide mistakes. |
| satisfies: const theme = { ... } satisfies ThemeConfig | Yes | Yes | Variable type stays inferred; compile-time check only. |
Nested objects and arrays
satisfies works on nested literals and array literals. The outer object is checked against the target type, and inner literals keep their inferred types.
type Navigation = {
items: { label: string; href: string }[];
};
const nav = {
items: [
{ label: 'Home', href: '/' },
{ label: 'About', href: '/about' },
],
} satisfies Navigation;
Each item in nav.items keeps its literal href values for autocompletion, while the array is still validated against Navigation.
Expected checks
- Run the type checker without emitting files:
npx tsc --noEmit
Run in the project root. No special permissions are required. Expected result: no output when the object matches the target type; a type error when a property is missing, has the wrong type, or is an excess property not declared in the target type.
- Hover over the variable in an editor with TypeScript language services. Confirm the inferred type shows literal property types, for example mode: "dark", not mode: string.
Limitations and recovery options
- No runtime validation. satisfies is erased at compile time. It cannot validate data from APIs, user input, or configuration files. Use a runtime schema validator such as Zod for untrusted data.
- Inferred type, not target type. The variable's type is its inferred literal type, not ThemeConfig. If a function parameter or return type annotation requires exactly ThemeConfig and inference causes a mismatch, add an explicit type annotation instead of or alongside satisfies.
- Excess property checking. Extra properties on the object literal produce a compile error. Remove the property or add it to the target type.
- TypeScript older than 4.9. satisfies is a syntax error. Upgrade TypeScript or use a type annotation with a separate as const assertion where literal preservation is needed.
Verify the result
- Create check-satisfies.ts with a compatible object using satisfies.
- Run npx tsc --noEmit check-satisfies.ts and confirm it exits without errors.
- Change one property to an incompatible value and run the command again. Confirm a type error appears.
- Hover over the variable to confirm literal types are preserved.
No rollback is needed because satisfies is a compile-time construct and does not change runtime state.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.