satisfies: Enforce Shape Without Losing Literal Types
Use the satisfies operator to validate objects (routes, feature flags, configs) while preserving literals for great inference and fewer casts.
F
Frontend Interview Team
March 01, 2026
What you’ll learn
- Why
as constis often not enough - How
satisfiesenforces a contract without widening your values - Real patterns: route tables, feature flags, and event maps
30‑second interview answer
satisfies checks that a value conforms to a type, but it keeps the value’s most specific inferred type. That makes it ideal for config objects where you want compile-time validation without losing literal types. Compared to const x: SomeType = ..., satisfies avoids unwanted widening.
The problem: annotation widens your literals
type RouteTable = Record<string, { path: string; auth: "public" | "private" }>;
const routes: RouteTable = {
home: { path: "/", auth: "public" },
settings: { path: "/settings", auth: "private" }
};
routes.home.path; // string (widened)Sometimes you want "/" as a literal type.
satisfies keeps literals while enforcing the contract
type RouteTable = Record<string, { path: `/${string}`; auth: "public" | "private" }>;
const routes = {
home: { path: "/", auth: "public" },
settings: { path: "/settings", auth: "private" }
} satisfies RouteTable;
routes.home.path; // "/" (literal!)You get:
- Contract enforcement (
pathmust start with/) - Literal inference for downstream typing
Pattern: route helpers with perfect inference
type Routes = typeof routes;
type RouteName = keyof Routes;
function linkTo<R extends RouteName>(name: R) {
return routes[name].path;
}
const a = linkTo("home"); // "/"
const b = linkTo("settings"); // "/settings"Pattern: feature flags with safe keys
type Flag = { owner: "growth" | "core"; rollout: 0 | 10 | 50 | 100 };
type FlagMap = Record<string, Flag>;
const flags = {
newNav: { owner: "growth", rollout: 10 },
fasterSearch: { owner: "core", rollout: 50 }
} satisfies FlagMap;
type FlagName = keyof typeof flags;Now FlagName is a safe union: "newNav" | "fasterSearch".
Common mistakes
- Using
as SomeTypeto “force” a config (hides real errors) - Overusing
as consteverywhere instead of usingsatisfiesstrategically
Production rule of thumb
Use satisfies for config objects and lookup tables:
- Routes
- Events
- Permissions
- Feature flags
It gives you strict validation + great inference.
Interview questions
-
Q: How is
satisfiesdifferent from a type annotation?- A: Annotation sets the variable’s type (often widening).
satisfiesonly checks compatibility and keeps narrow inference.
- A: Annotation sets the variable’s type (often widening).
-
Q: When is it most useful?
- A: Config/lookup objects where you want both validation and literal types.
Quick recap
satisfiesvalidates shape but preserves literals.- It’s perfect for route tables/config.
- Prefer it over casts for safer, cleaner code.