Careeroza
Const Assertions
as const
as const tells TypeScript to infer the narrowest type: string and number literals stay literal, arrays become readonly tuples and object properties become readonly.
Example
const sizes = ["S", "M", "L"]; // string[]
const sizesConst = ["S", "M", "L"] as const; // readonly ["S", "M", "L"]
type Size = (typeof sizesConst)[number]; // "S" | "M" | "L"
const config = { currency: "INR", maxQty: 10 } as const;
// config.currency is "INR", config.maxQty is 10, both readonly
function pickSize(s: Size): string { return "Size " + s; }
console.log(sizes.length, pickSize(sizesConst[1]), config.currency, config.maxQty);Output
3 Size M INR 10
Readonly Result
Example
Everything under as const is readonly (TS2540, TS2339).
const config = { currency: "INR", tiers: ["silver", "gold"] } as const;
config.currency = "USD";
config.tiers.push("platinum");Compiler output (tsc)
Line 2: error TS2540: Cannot assign to 'currency' because it is a read-only property. Line 3: error TS2339: Property 'push' does not exist on type 'readonly ["silver", "gold"]'.
Best of Both: as const satisfies
Example
Combine them to get literal types and a shape check.
type Plan = { name: string; pricePerMonth: number };
const PLANS = [
{ name: "Mobile", pricePerMonth: 149 },
{ name: "Premium", pricePerMonth: 649 },
] as const satisfies readonly Plan[];
type PlanName = (typeof PLANS)[number]["name"]; // "Mobile" | "Premium"
const choice: PlanName = "Premium";
console.log(choice, PLANS.find((p) => p.name === choice)?.pricePerMonth);Output
Premium 649