@clementvial

Developer from Canada 🇨🇦
Product, infrastructure, AI, and web3.
Mostly on AWS and Cloudflare.

All notes

satisfies Fixed How I Type Config Objects

Every project ends up with a config object mapping names to settings, and typing it used to mean choosing between two bad options.

Annotate it and you get checking, but the keys widen:

routes.ts
const routes: Record<string, Route> = {
home: { path: '/', auth: false },
admin: { path: '/admin', auth: true },
};
type RouteName = keyof typeof routes; // string
routes.hme; // no error, it's a Record<string, Route>

Leave the annotation off and the keys survive, but nothing validates the values. A typo in auth sails through, and it’s boolean | string now because inference took the union of what it saw.

satisfies gives you both. It checks the value against a type without replacing the inferred one:

routes.ts
const routes = {
home: { path: '/', auth: false },
admin: { path: '/admin', auth: true },
} satisfies Record<string, Route>;
type RouteName = keyof typeof routes; // 'home' | 'admin'
routes.hme; // error

Same checking, and RouteName is now a union you can use in a function signature. Getting a wrong route name rejected at the call site is the actual payoff.

Where it earns its keep

Narrowing survives, which is the part I didn’t expect. Give a property the type string | string[] in your constraint and pass a plain string, and the inferred type stays string. No cast needed to call .toUpperCase() on it later.

It also composes with as const when you want the whole thing readonly:

routes.ts
const routes = { … } as const satisfies Record<string, Route>;

Order matters. as const first, then satisfies.

Where it doesn’t help

satisfies is compile-time only. It disappears at runtime, so it’s the wrong tool for anything crossing a boundary: request bodies, environment variables, API responses. Those still need a parser like Zod.

The rule I settled on is simple enough to apply without thinking. Data I wrote gets satisfies. Data someone else wrote gets parsed.