TypeScript: unknown vs any
Both any and unknown are top types in TypeScript, meaning they can hold any value. However, they behave very differently when you try to use those values.
1. The any Type (The "Escape Hatch")
any essentially disables type checking for that variable. It allows you to do anything with the value, even if it doesn't exist.
- Assignable to anything: Yes.
- Assignable from anything: Yes.
- Access properties/methods: Yes (without checks).
let value: any;
value = true; // OK
value = 42; // OK
value = "hello"; // OK
// DANGER ZONE: TypeScript allows all of this, but it might crash at runtime
value.foo.bar; // OK (Compiler assumes you know what you are doing)
value(); // OK
value.trim(); // OK
const num: number = value; // OK
Verdict: Use any only when migrating legacy JavaScript code or when you truly cannot know the type and don't care about safety.
2. The unknown Type (The Safe Alternative)
unknown is the type-safe counterpart to any. Like any, it can hold any value. Unlike any, you cannot perform arbitrary operations on it. You must "narrow" the type first.
- Assignable to anything: No (only to
unknownorany). - Assignable from anything: Yes.
- Access properties/methods: No (Compiler blocks you).
let value: unknown;
value = true; // OK
value = 42; // OK
// SAFETY: TypeScript blocks these operations
// value.foo.bar; // Error: Object is of type 'unknown'.
// value(); // Error: Object is of type 'unknown'.
// value.trim(); // Error: Object is of type 'unknown'.
// const num: number = value; // Error: Type 'unknown' is not assignable to type 'number'.
3. How to use unknown
To use an unknown variable, you must prove to TypeScript what it is using Type Narrowing (Type Guards).
let value: unknown = "Hello World";
// 1. Check the type
if (typeof value === "string") {
// TypeScript knows 'value' is a string here
console.log(value.toUpperCase());
}
// 2. Custom Type Guard
function isNumberArray(x: unknown): x is number[] {
return Array.isArray(x) && x.every(val => typeof val === 'number');
}
if (isNumberArray(value)) {
// TypeScript knows 'value' is number[] here
console.log(value.map(n => n * 2));
}
Summary: Always prefer unknown over any when typing inputs where the value is dynamic (e.g., API responses, JSON.parse results). It forces you to handle the type safely.