satisfies operator
TypeScript · Reference cheat sheet
satisfies operator
TypeScript · Reference cheat sheet
📋 Overview
satisfies T (TS 4.9+) checks that an expression is assignable to T while preserving the expression’s more specific inferred type. Use it for config objects, route maps, and as const data that must match a contract without widening.
🔧 Core concepts
- Check without widen — validates against
T, keeps literal / tuple detail. - vs annotation —
const x: T = …widens toT;satisfieskeeps narrow type. - vs
as T— assertion skips checking;satisfieserrors on mismatch. - Combines with
as const— deep readonly + literal types + shape check.
💡 Examples
type ColorMap = Record<string, string | RGB>;
type RGB = [number, number, number];
// Annotation widens values → string | RGB everywhere
const colorsAnnotated: ColorMap = {
red: [255, 0, 0],
green: "#00ff00",
};
// satisfies: red stays a tuple, green stays "#00ff00"
const colors = {
red: [255, 0, 0],
green: "#00ff00",
} satisfies ColorMap;
colors.red.map((n) => n / 255); // OK — tuple known
colors.green.toUpperCase(); // OK — string literal methods
const palette = {
primary: "#336699",
secondary: "#99cc33",
} as const satisfies Record<string, `#${string}`>;
type Route = { path: string; auth: boolean };
const routes = {
home: { path: "/", auth: false },
admin: { path: "/admin", auth: true },
} satisfies Record<string, Route>;
type RouteKey = keyof typeof routes; // "home" | "admin"// Error: missing required field
// const bad = { path: "/" } satisfies Route;⚠️ Pitfalls
satisfiesdoes not change the runtime value — validation is type-only.- Excess property checks still apply to fresh object literals against
T. - Nested objects may still widen unless you also use
as const. - Not a substitute for runtime validation of external input.
- Older TS (<4.9) — use annotated helpers or dual variables instead.