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

  • satisfies gives you both type validation and narrow type inference
  • Unlike as, satisfies validates the actual value against the type
  • Especially useful for config objects, route maps, and theme constants
  • Available since TypeScript 4.9