The satisfies operator in TypeScript
What is the satisfies Operator?
The satisfies operator (introduced in TypeScript 4.9) lets you validate that a value conforms to a type while preserving its narrowed (more specific) type β unlike type annotation which widens it.
The Problem satisfies Solves
typescript
type Colors = Record<string, string | number[]>;
// With type annotation β loses specificity
const colors: Colors = {
red: "#ff0000",
green: [0, 255, 0],
};
colors.red.toUpperCase(); // β Error: Property 'toUpperCase' does not exist on type 'string | number[]'
colors.green.map(x => x); // β Error: same reason
// With satisfies β keeps narrow types
const colors = {
red: "#ff0000",
green: [0, 255, 0],
} satisfies Colors;
colors.red.toUpperCase(); // β
TypeScript knows it's a string
colors.green.map(x => x); // β
TypeScript knows it's number[]How It Works
| Approach | Validates type? | Preserves narrow type? |
|---|---|---|
const x: Type = value | β | β (widened to Type) |
const x = value as Type | β (no real check) | β |
const x = value satisfies Type | β | β |
Practical Use Cases
Configuration Objects
typescript
type Route = {
path: string;
method: "GET" | "POST" | "PUT" | "DELETE";
handler: string;
};
type Routes = Record<string, Route>;
const routes = {
getUsers: {
path: "/api/users",
method: "GET",
handler: "UserController.getAll",
},
createUser: {
path: "/api/users",
method: "POST",
handler: "UserController.create",
},
} satisfies Routes;
// TypeScript knows exact keys: "getUsers" | "createUser"
// And exact method types: "GET", "POST" (not just the union)
routes.getUsers.method; // "GET" (not "GET" | "POST" | "PUT" | "DELETE")Theme Definition
typescript
type Theme = Record<string, string | { light: string; dark: string }>;
const theme = {
primary: "#007bff",
background: { light: "#ffffff", dark: "#1a1a2e" },
text: { light: "#000000", dark: "#e0e0e0" },
} satisfies Theme;
// TypeScript preserves the structure
theme.primary.toUpperCase(); // β
knows it's string
theme.background.light; // β
knows it's an object with .lightEnum-like Constants
typescript
type StatusCode = 200 | 201 | 400 | 401 | 404 | 500;
const STATUS = {
OK: 200,
CREATED: 201,
BAD_REQUEST: 400,
UNAUTHORIZED: 401,
NOT_FOUND: 404,
SERVER_ERROR: 500,
} satisfies Record<string, StatusCode>;
// STATUS.OK is 200 (literal), not just StatusCode
type OkStatus = typeof STATUS.OK; // 200Combined with as const
typescript
const palette = {
red: "#ff0000",
green: "#00ff00",
blue: "#0000ff",
} as const satisfies Record<string, `#${string}`>;
// Values are readonly literal types AND validated as hex colorsImportant:
Use satisfies when you want to validate that a value matches a type while keeping the more specific type information. It's a best-of-both-worlds approach β type safety without losing type narrowing. It's especially useful for configuration objects, theme definitions, and constant maps.
Short Answer
Interview readyPremium
A concise answer to help you respond confidently on this topic during an interview.