any, unknown, never
| any opts out | |
| unknown is honest | |
| never happens | |
| Which to reach for |
any opts out
The any type switches the checker off for one variable. Any value fits and any operation is allowed, so errors move back to run time where they are harder to find:
let loose: any = 5;
loose = "now text";
console.log(loose);
now text
The snippet compiles and prints without complaint. Reach for any only at the border with untyped code, and replace it with a precise type as soon as the shape is known.
unknown is honest
The unknown type also accepts every value, but it refuses to let you use the value before a check. That single demand removes the danger that makes any risky:
function read(value: unknown): string {
if (typeof value === "string") {
return value;
}
return "not text";
}
console.log(read("hi"));
hi
Inside the if branch, typeof has proven the value is a string, so returning it is safe. Outside the branch the value is still unknown, and only the fallback text is returned.
never happens
The never type marks code that cannot produce a value because it never returns. Functions that always throw errors are the classic case:
function fail(message: string): never {
throw new Error(message);
}
Nothing can be assigned from fail because there is nothing to assign: the throw ends the call every time. The compiler uses never to prove that all paths of a check were handled.
Which to reach for
Default to unknown for values of unclear shape, keep never for functions that cannot return, and leave any for quick migration drafts. The pattern below shows the honest habit in three lines:
const input: unknown = "data";
if (typeof input === "string") {
console.log(input.toUpperCase());
}
DATA
Accept the value as unknown, prove it with typeof, and only then call string methods. That order keeps the compiler as your reviewer instead of a silent witness.
Next: Arrays and tuples
Article author: Arthur Isaev