TypeScript satisfies Operator: Type Safety Without Losing Inference
Problem
When typing objects in TypeScript, you typically do this:
type Config = {
api: string;
port: number;
debug: boolean;
};
const config: Config = {
api: "https://api.example.com",
port: 3000,
debug: true,
};
The issue is that explicit type annotations widen the inferred type. config.api becomes string instead of the literal "https://api.example.com", weakening autocomplete.
Using as const makes everything readonly, and as Config skips type checking entirely.
Solution
Use the satisfies operator.
const config = {
api: "https://api.example.com",
port: 3000,
debug: true,
} satisfies Config;
// config.api type: "https://api.example.com" (literal type!)
// config.port type: 3000
// Still validated against Config
A practical use case is route configuration:
type Route = {
path: string;
method: "GET" | "POST" | "PUT" | "DELETE";
};
const routes = {
getUsers: { path: "/users", method: "GET" },
createUser: { path: "/users", method: "POST" },
updateUser: { path: "/users/:id", method: "PUT" },
} satisfies Record<string, Route>;
// routes.getUsers.method type: "GET" (not string!)
The difference from as is clear:
// as allows lies (dangerous)
const bad = { api: 123 } as Config; // No error!
// satisfies actually validates
const good = { api: 123 } satisfies Config; // Error!
Key Points
satisfiesgives you both type validation and narrow type inference- Unlike
as,satisfiesvalidates the actual value against the type - Especially useful for config objects, route maps, and theme constants
- Available since TypeScript 4.9