TypeScript Type Assertions and satisfies
TypeScript type assertions tell the compiler "trust me, this value has this type". They do not convert or check anything at runtime, so use them only when you know more than the compiler does.
The as Keyword
A common case is the DOM: querySelector returns a general Element, but you know it is an input.
const input = document.querySelector("#email") as HTMLInputElement;
input.value = "me@example.com"; // .value exists on HTMLInputElement
// Better: use a generic or a check
const el = document.querySelector<HTMLInputElement>("#email");
if (el) console.log(el.value);me@example.com
Assertions Do Not Validate Data
Asserting the type of parsed JSON only silences the compiler. If the data is wrong, the bug appears at runtime. Validate external data with a type guard or a library like Zod.
type User = { name: string; age: number };
const user = JSON.parse('{"name":"Ali"}') as User;
console.log(user.age.toFixed(0)); // compiles, but age is undefinedTypeError: Cannot read properties of undefined (reading 'toFixed')
The Non-null Assertion (!)
Adding ! after an expression removes null and undefined from its type. It is a shortcut that can hide real bugs; an explicit check or ?. is usually safer.
const map = new Map<string, number>([["rice", 120]]);
const qty = map.get("rice")!; // number, not number | undefined
console.log(qty + 1);
const safer = map.get("tea") ?? 0;
console.log(safer);121 0
The satisfies Operator
satisfies checks that a value matches a type without changing the inferred type. You get validation and keep the precise literal types, which a plain annotation would widen.
type Route = { path: string; auth: boolean };
const routes = {
home: { path: "/", auth: false },
dashboard: { path: "/dashboard", auth: true },
} satisfies Record<string, Route>;
// keys are still known exactly:
console.log(routes.dashboard.path);
// routes.settings; // Error: Property 'settings' does not exist./dashboard
Choosing the Right Tool
- Type annotation (: T): declare what a variable must be
- satisfies T: check a value against T but keep its specific type
- as const: freeze a literal into readonly, exact values
- as T: last resort when you know the type better than the compiler
- Avoid double assertions like value as unknown as T unless absolutely necessary
Frequently asked questions
What is the difference between as and satisfies in TypeScript?
as overrides the type the compiler sees, with almost no checking. satisfies verifies the value matches the type but keeps the more specific inferred type.
Is a type assertion the same as type casting?
No. Casting in other languages converts values. A TypeScript assertion only changes compile-time types; the runtime value is untouched.
When is the non-null assertion operator OK to use?
When you are certain a value exists, for example an element you just created. Prefer explicit checks for anything that depends on outside data.