TypeScript Tutorial
TypeScript Type Assertions
as T tells the compiler you know the type. Use it when you have information the checker cannot see.
A claim, not a conversion
value as string does not change the value at run time. It tells tsc to treat that expression asstring. There is no extra check unless you write one. If you are wrong, the program can throw later when you call a string method on something else.
C++ operator overloading teaches the compiler a new meaning for a symbol. A TypeScript assertion does not overload anything. It is closer to a cast: you take responsibility for a type the checker cannot prove. Prefer narrowing (typeof, instanceof, in) when you can.
unknown first, then as
Values from outside your program — parsed JSON, a loosely typed helper — often arrive as unknown(or should). You may not call methods on unknown. Assert only after you know the shape, or assert in a tiny helper that you have already validated.
Example
function asText(value: unknown): string {
if (typeof value !== "string") {
throw new Error("not a string");
}
return value as string;
}
const raw: unknown = "typed later";
const text = asText(raw);
console.log(text.length);
console.log(text.toUpperCase());Output is 11 then TYPED LATER. After typeof value !== "string" returns, tsc already treats value as string. The as string is redundant here and kept so you see the syntax next to unknown. The throw is the real safety.
Run this at /typescript/try. Change raw to 7 and the helper throwsnot a string instead of calling .length on a number.
Assert an object shape
When you have already checked that a value is a non-null object with the keys you need, as can name that shape. Keep the check and the assertion in one function so callers never see unknown.
Example
type Pair = { n: number };
function asPair(value: unknown): Pair {
if (typeof value !== "object" || value === null || !("n" in value)) {
throw new Error("not a pair");
}
return value as Pair;
}
const raw: unknown = { n: 3 };
const pair = asPair(raw);
console.log(pair.n);Output is 3. "n" in value narrows enough to make the assertion honest for this tutorial. A full validator would also check typeof of n. Start withunknown, not any: any turns the checker off.
as const is a different assertion
You already used as const in the const chapter. That assertion asks for a narrower type (literal tuples, readonly fields). as string asks for a wider or different view of an existing value. Do not mix the two in your head: one locks literals, the other is a claim about a value you already have.
Example
const codes = [200, 404] as const;
const first: number = codes[0];
console.log(first);
const mystery: unknown = codes[1];
const status = mystery as 404;
console.log(status);Output is 200 then 404. The last as 404 is a claim. Ifmystery were actually 200, tsc would still believe you. That is why unknown-plus-check comes first.
When not to assert
| Situation | Prefer |
|---|---|
| Value might be null | An if, ??, or ?. |
| Union of two types you control | typeof or a discriminant field |
| Parsed input | unknown, then a helper that throws or returns |
| You are tired of errors | Fix the type, not as any |
Angle-bracket assertions such as <string>value exist in TypeScript. This tutorial usesvalue as string only. The <string> form collides with JSX and is easy to misread.
Narrow when you can, assert when you must
Start from unknown. Check. Then as T if the checker still cannot see what you proved. Next: generics, which write one function for many types so you need fewer assertions in the first place.