Engrain by ByteRush

TS.02.04 Mid-level· 10 minCore — asked often

as const, satisfies and literal inference: precise types without lying

Why TypeScript widens "md" to string, how as const keeps literal types, how satisfies checks a value without losing its type, and why as is an assertion, not a conversion.

Comes up in: Coding

Learn#

Hari’s design system has size: "sm" | "md" | "lg". He writes const props = { size: "md" } and passes it on. Error: string is not assignable to "sm" | "md" | "lg". TypeScript widened "md" to string, because object properties can change later.

A const assertion, as const, keeps the exact values: literal types, readonly properties, and fixed-length tuples. ["sm", "md", "lg"] as const has the type readonly ["sm", "md", "lg"].

Three ways to connect a value to a type behave differently:

type Routes = Record<string, { path: string }>;

const annotated: Routes = { home: { path: "/" }, cart: { path: "/cart" } };
const checked = { home: { path: "/" }, cart: { path: "/cart" } } satisfies Routes;
const asserted = JSON.parse('{"home": {}}') as Routes;

annotated.chekout.path;    // no error: the annotation forgot which keys exist
checked.chekout.path;      // error: satisfies kept the real keys
asserted.home.path.length; // no error, but it crashes at runtime
const typo = { home: { pth: "/" } } satisfies Routes; // error: still checked
TypeScript compiler output (verified)
example.ts(8,9): error TS2339: Property 'chekout' does not exist on type '{ home: { path: string; }; cart: { path: string; }; }'.
example.ts(10,24): error TS2561: Object literal may only specify known properties, but 'pth' does not exist in type '{ path: string; }'. Did you mean to write 'path'?
Annotation, satisfies and as on the same objectStep 1 of 4

State

  • annotated: Record<string, { path }>

Console

    empty

    With an annotation, the variable's type IS Routes. TypeScript forgets that only home and cart exist.

    Read the steps as text
    1. With an annotation, the variable's type IS Routes. TypeScript forgets that only home and cart exist.
    2. With satisfies, TypeScript checks the value against Routes but keeps the type it inferred.
    3. With as, TypeScript believes you. Nothing is checked or converted at runtime.
    4. So checked.chekout is an error, annotated.chekout is not, and asserted.home.path crashes at runtime.

    Predict#

    Predict first

    const n = '42' as unknown as number; console.log(n + 1) — what prints?

    Interview angle#

    Say it like this — about 30 seconds

    “A type annotation sets the variable’s type, and the value must match it, but you lose the more precise inferred type. satisfies checks the value against a type and keeps the inferred type, so known keys and literals stay. as is a type assertion: it tells the compiler to trust me, checks almost nothing, and changes nothing at runtime. as const keeps literal values and makes everything readonly, which is how I derive union types from constant arrays.”

    Stays on your device. Nothing is uploaded.
    Follow-up What is the difference between satisfies, a type annotation and as?
    Annotation: the type wins. satisfies: checked, inferred type kept. as: not really checked, you take the risk.
    Follow-up What does as const do?
    Makes literals keep their exact types, properties readonly, and arrays readonly tuples.
    Follow-up When is as acceptable?
    After a real runtime check the compiler cannot follow, or in tests. Prefer a type guard (TS.02.03).

    Practice#

    Guided

    Make ROLES precise with as const, derive Role, and check routes with satisfies so its keys are kept.

    Done when

    • Role is "admin" | "editor" | "viewer", derived from ROLES.
    • isRole returns true only for those three strings.
    • routeFor takes keyof typeof routes, so a misspelled route name is a compile error.
    • routes uses satisfies, not an annotation or as.
    Your solution
    Ctrl/⌘ + Enter

    Remember#

    Try to answer each card before you open it. Then add them to your reviews.

    What does as const do to an array of strings?

    Makes it a readonly tuple of the exact string literals.

    satisfies vs annotation: what does satisfies keep?

    The value's own inferred type, after checking it.

    What does as do at runtime?

    Nothing. It changes only what the compiler believes.

    How do you get a union type from a const array?

    (typeof arr)[number], with the array declared as const.

    Go deeper

    Four layers. Stop at the one your interview needs; each ends with a quick check.

    The core ideaEvery round

    const x = "md" has type "md"; let x = "md" is widened to string, because it can change. Object properties and array items widen too, since they are mutable.

    Check yourself: Why is let x = 'md' typed string but const x = 'md' typed 'md'?

    A let can be reassigned, so TypeScript widens it; a const cannot.

    How it works underneathSenior rounds

    as const makes arrays readonly tuples, so .push is a compile error and (typeof arr)[number] gives the union of items (TS.05.01).
    It works only on literals, not on variables or function calls Source: TypeScript 3.4: const assertions.

    Check yourself: What is the type of ['a', 'b'] as const?

    readonly ['a', 'b']

    Edge cases and trapsWhere people slip
    A type assertion rejects only types that do not overlap at all. as unknown as T skips even that, and JSON.parse(text) as T is always allowed, because any matches everything.
    Check yourself: Why does '42' as number fail but '42' as unknown as number compile?

    as rejects types with no overlap; going through unknown removes that last check.

    In productionStaff-level answers

    Use satisfies for config, routes, theme tokens and lookup tables: the shape is checked, and autocomplete still knows every key. Combine both: { … } as const satisfies Config gives literal types and a check Source: TypeScript 4.9: The satisfies operator.

    Check yourself: Where is satisfies most useful?

    Config objects and lookup tables you want checked but still precisely typed.

    Finished the five steps? Mark it, and its cards join your reviews.

    Last checked 2026-10-31. Spot a mistake? Use “Report an error” below — fixes are listed on the corrections page.

    Interview questions this answers

    • What is the difference between satisfies, a type annotation and as?
    • What does as const do?