any vs unknown vs never in TypeScript
These three types sit at the edges of TypeScript's type system and are often confused. Using the right one is the difference between real safety and false confidence.
any: switch off checking
let data: any = JSON.parse(input);
data.user.name.toUpperCase(); // compiles, may crash at runtime
const n: number = data; // any is assignable to everything
any spreads silently: anything touching it also loses type safety. Treat it as a last resort, and enable the noImplicitAny check (part of strict).
unknown: safe "I don't know yet"
let data: unknown = JSON.parse(input);
data.user; // Error: 'data' is of type 'unknown'
if (typeof data === 'object' && data !== null && 'user' in data) {
// narrowed, now you can work with it
}
You can assign anything to unknown, but you must narrow or validate it before using it. Use it for JSON, catch variables and third-party callbacks.
try {
await save();
} catch (err: unknown) {
const message = err instanceof Error ? err.message : String(err);
logger.error(message);
}
never: impossible
never is the type with no values. It appears for functions that never return and for branches that can't happen:
function fail(message: string): never {
throw new Error(message);
}
type Shape = { kind: 'circle' } | { kind: 'square' };
function area(s: Shape) {
switch (s.kind) {
case 'circle': return 1;
case 'square': return 2;
default: {
const exhaustive: never = s; // errors if a new kind is added
return exhaustive;
}
}
}
Summary
any- "trust me" (avoid).unknown- "could be anything, check first" (prefer).never- "this can't happen" (use for exhaustiveness and throwing functions).
Was this article helpful?
Comments
No comments yet. Have a question or a tip? Be the first to share it.