Type Assertions

Sometimes you know more about a value than TypeScript can work out. A type assertion — written with as — tells the compiler to treat a value as a particular type. It's powerful and occasionally necessary, but it's also a way to tell the compiler something false.

The as keyword

The classic example is the DOM. document.getElementById can return any kind of element, so its return type is the general HTMLElement | null. If you know it's an input, you can say so:

TS dom.ts
const field = document.getElementById("email") as HTMLInputElement;

console.log(field.value);

Without the assertion, field.value would be an error, because a generic HTMLElement has no value property. With it, you get full autocomplete for inputs.

Important: an assertion is not a conversion. It changes nothing at runtime — it only changes what the compiler believes. If the element is actually a <div>, field.value will silently be undefined.

Assertions don't convert values

TS not-conversion.ts
const input: unknown = "42";

const wrong = input as number;
const right = Number(input);

console.log(typeof wrong, typeof right);
Output
string number

TypeScript accepted input as number, but the value is still the string "42". To actually change a value's type, use a real conversion such as Number(), String() or parseInt().

Assertions must be plausible

TypeScript rejects assertions between types that can't possibly overlap:

TS impossible.ts
const count = 5;
const text = count as string;
tsc output
error TS2352: Conversion of type 'number' to type 'string' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.

As the message hints, you can force it with count as unknown as string — a "double assertion". If you find yourself writing one, it's almost always a sign the types are wrong somewhere upstream.

The angle-bracket form

An older syntax, <HTMLInputElement>field, does the same thing as field as HTMLInputElement. It can't be used in .tsx files because it clashes with JSX, so as is the standard choice today.

as const

as const is a special assertion that makes TypeScript infer the narrowest possible type: literal values instead of string/number, readonly properties, and readonly tuples instead of arrays:

TS as-const.ts
const ROLES = ["admin", "editor", "viewer"] as const;
type Role = (typeof ROLES)[number];

function canEdit(role: Role) {
  return role !== "viewer";
}

console.log(ROLES.map(r => `${r}: ${canEdit(r)}`).join(", "));
Output
admin: true, editor: true, viewer: false

Here ROLES is readonly ["admin", "editor", "viewer"], and (typeof ROLES)[number] extracts the union "admin" | "editor" | "viewer" (lesson 24 explains this syntax). You get a runtime list and a matching type from one source of truth — a popular alternative to enums.

satisfies: check without changing the type

A type annotation replaces the inferred type with the one you wrote. Sometimes that loses useful detail:

TS annotation-loses.ts
type Colors = Record<string, string | number[]>;

const palette: Colors = {
  primary: "#d6336c",
  accent: [255, 200, 0],
};

palette.primary.toUpperCase();
tsc output
error TS2339: Property 'toUpperCase' does not exist on type 'string | number[]'.

The satisfies operator checks that a value matches a type but keeps the more specific inferred type:

TS satisfies.ts
type Colors = Record<string, string | number[]>;

const palette = {
  primary: "#d6336c",
  accent: [255, 200, 0],
} satisfies Colors;

console.log(palette.primary.toUpperCase());
console.log(palette.accent.length);
Output
#D6336C
3

The object is still validated against Colors (a typo or wrong value type would be an error), but TypeScript remembers that primary is a string and accent is an array.

Assertion vs annotation vs satisfies

SyntaxChecks the value?Resulting type
const x: T = valueYes — must be assignable to TT
const x = value as TBarely — only rejects impossible casesT
const x = value satisfies TYes — must be assignable to TThe inferred type of value

Prefer annotations and satisfies; reach for as only when you genuinely know something the compiler can't.

Try it yourself

Try it yourself
Console output