What does the satisfies operator add over plain annotations?
Take a moment.
Say your answer out loud or write it down first — retrieval is what makes it stick. Reveal when you're ready.
Short answer
satisfies validates a value against a type while preserving the value's inferred (often narrower) type. Plain annotations widen literals and lose specificity; satisfies keeps both safety and precision.
Detailed explanation
Annotating const config: Config = {...} checks compliance but *widens* the variable to Config — literal values become their general types ('dark' widens to string), losing autocomplete and exactness downstream. satisfies flips it: const config = {...} satisfies Config verifies every requirement while keeping inferred narrowness — config.theme stays 'dark' | 'light' instead of string, excess-property checking still applies during validation, and no duplicate type declaration is needed. Ideal cases: typed constant maps (routes, feature flags, theme tokens) where consumers benefit from precise literal types, and validating objects whose specific shape matters later. Limitations: it's expression-level (not for function returns — those still use annotations), available since TS 4.9, and codebases on older versions rely on as const + separate checks. Knowing when NOT to use it — public API boundaries where widening is desirable — shows balanced judgment.
Example
type ThemeConfig = Record<string, { dark: boolean; accent: string }>;
const themes = {
sunset: { dark: true, accent: '#ff7a59' },
ocean: { dark: false, accent: '#2563eb' },
} satisfies ThemeConfig;
themes.sunset.accent; // type stays '#ff7a59' (literal!) — not string
// typo key 'sunet' ❌ caught by satisfies checkInterview tip
Contrast directly with annotation-widening in one example — the literal-preservation demo is the entire answer. Mention TS 4.9+ availability.
Common mistakes
- Thinking replaces as const entirely — they solve different problems.
- Using satisfies where function return annotations are needed.