The satisfies Operator

The satisfies operator validates that a value conforms to a type without widening the value's inferred type, so you get both contract-checking and the precise types you actually wrote.

Learn The satisfies Operator in our free TypeScript course — an interactive lesson with runnable examples, a practice exercise and a quick reference.

Part of the free TypeScript course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

Think of an airport security check. An annotation ( : ) is like swapping your bag for a standard-issue one that "fits the rules" — it passes, but you've lost your specific belongings (precise types). An assertion ( as ) is waving a badge to skip the scanner entirely — fast, but nothing was actually checked. satisfies is the proper scan: your own bag goes through, it's verified against the rules, and you keep everything exactly as it was.

1. Check Without Widening

Write value satisfies Type and TypeScript verifies the value matches the type — reporting any mismatch — while leaving the value's inferred type untouched. So a port: 8080 stays a number (not widened to ), and number operations on it remain valid. You get the safety of a contract with none of the precision loss.

2. satisfies vs : vs as

Three constructs relate a value to a type, and they behave very differently. A type annotation ( : ) declares the variable to be that type, often widening literals away. An assertion ( as ) forces the type with no validation. satisfies sits between them: it validates like an annotation but preserves the precise inferred type like nothing else.

3. Real-World: Config Objects & Route Maps

The pattern shines on objects mixing value kinds — a route map with string paths and URL-builder functions, a theme with literal color tokens, a handler dictionary. You want to guarantee every value fits the contract, yet still call the functions and read the literals directly. satisfies gives you that: validated as a whole, precise per property.

🎯 Your Turn

Because satisfies keeps each size a number , you can do math and append a unit. Fill in the blank marked ___ with the CSS unit, then run it.

No blanks this time — just a brief and a starting outline. Build the dispatcher yourself, run it, and check your output against the example in the comments.

Practice quiz

What does 'value satisfies Type' do?

  • Casts the value to Type
  • Converts the value at runtime
  • Validates the value against Type without changing its inferred type
  • Widens the value to Type

Answer: Validates the value against Type without changing its inferred type. satisfies checks conformance while preserving the precise inferred type.

After 'const c = { port: 8080 } satisfies Record<string, number>', what is the type of c.port?

  • number
  • string | number
  • 8080 widened to any
  • unknown

Answer: number. satisfies keeps the precise inference, so c.port stays number.

How does a ': Type' annotation differ from satisfies?

  • They are identical
  • The annotation skips checking
  • The annotation is runtime-only
  • The annotation declares the variable to be Type and can widen it

Answer: The annotation declares the variable to be Type and can widen it. An annotation makes the variable that type, often widening literals; satisfies only checks.

How does 'as Type' differ from satisfies?

  • as performs validation too
  • as asserts with no real check, so wrong values pass silently
  • as preserves inference better
  • they are the same

Answer: as asserts with no real check, so wrong values pass silently. as is an unchecked assertion; satisfies actually validates the value.

Does satisfies change the value at runtime?

  • No, it is erased - compile-time only
  • Yes, it coerces
  • Yes, it freezes the value
  • Only in strict mode

Answer: No, it is erased - compile-time only. Like other type operators, satisfies adds nothing at runtime.

Why is satisfies ideal for a route map with strings and functions?

  • It runs the functions
  • It widens every value to a union
  • Each value keeps its exact type while the whole object is validated
  • It deletes the functions

Answer: Each value keeps its exact type while the whole object is validated. routes.home stays a string and routes.user stays callable - precise per property, validated as a whole.

What happens if a property's value violates the satisfies constraint?

  • It is silently ignored
  • You get a compile-time error
  • It throws at runtime
  • It is auto-corrected

Answer: You get a compile-time error. satisfies reports a mismatch as a compile error - that's the validation.

Wherever you were about to write 'as SomeShape' on a literal, you should prefer:

  • any
  • a double assertion
  • JSON.stringify
  • satisfies SomeShape

Answer: satisfies SomeShape. satisfies checks the value instead of trusting you blindly, so it's strictly safer.

Which combination gives deep readonly literals AND a contract check?

  • value as const
  • value as const satisfies T
  • value satisfies T
  • value as T

Answer: value as const satisfies T. as const makes deep readonly literals; satisfies adds the contract validation.

Which TypeScript version introduced the satisfies operator?

  • 3.0
  • 4.0
  • 4.9
  • 5.5

Answer: 4.9. satisfies requires TypeScript 4.9 or newer.