As Casting
Type casting (or Type Assertions) is how you tell TypeScript, "I know more about this value than you do."
The mental model
TypeScript infers types based on the code it can see. But sometimes, you have external knowledge (like the structure of a DOM element or a specific API guarantee). You use the as keyword to override TypeScript's inference.
This does not change the value at runtime. It only changes how the compiler treats it.
// document.getElementById returns HTMLElement | null
// But we know it's a canvas, and we know it exists.
const canvas = document.getElementById("my-canvas") as HTMLCanvasElement;
// Now we can safely access canvas-specific methods
const ctx = canvas.getContext("2d");
The danger of lying to the compiler
Type assertions are a blunt instrument. When you use as, you assume full responsibility. If you are wrong, TypeScript will not protect you, and your app will crash at runtime.
interface User { name: string; age: number; }
// We forgot 'age', but 'as User' silences the error!
const user = { name: "Alice" } as User;
console.log(user.age.toFixed()); // Runtime crash: user.age is undefined
Double Casting (as unknown as Type)
TypeScript is smart enough to prevent completely absurd casts. You cannot cast a string directly to a number.
If you really need to force a cast across incompatible types, you must first cast to unknown.
const num = 123;
// const str = num as string; // Error: Conversion of type 'number' to type 'string' may be a mistake
// The escape hatch:
const forced = num as unknown as string; // Valid: Compiles (but is very dangerous)
Avoid
aswhenever possible. Prefer type guards or proper type annotations. Useasonly when interacting with untyped external boundaries like the DOM where you have guaranteed external context.