Unknown Type
unknown is the type-safe alternative to any.
The mental model
When you type something as any, you are telling TypeScript to turn off all checks. You can call methods on it, pass it anywhere, and assume it's whatever you want.
When you type something as unknown, you are saying "I don't know what this is yet." TypeScript will aggressively prevent you from doing anything with an unknown value until you perform a type guard to prove what it is.
let unsafe: any = 10;
unsafe.toUpperCase(); // Valid: No compile error, but will crash at runtime
let safe: unknown = 10;
// safe.toUpperCase(); // Error: Object is of type 'unknown'
if (typeof safe === "string") {
safe.toUpperCase(); // Valid, we proved it's a string
}
Where you should use it
- API Responses: When you fetch data from an external source, it is truly
unknownuntil you validate it. catchblocks: In TypeScript 4.4+, caught errors areunknownby default because you could theoretically throw anything in JavaScript, not justErrorobjects.
try {
throw "Just a string error";
} catch (error: unknown) {
// error.message // Error: object is of type 'unknown'
if (error instanceof Error) {
console.log(error.message); // Valid
} else if (typeof error === "string") {
console.log(error); // Valid
}
}
Forcing a cast from unknown
If you are absolutely certain of the type of an unknown value (e.g., you just validated it using a JSON schema library like Zod), you can use the as keyword to cast it without traditional type guards.
const response: unknown = getExternalData();
const user = response as User; // We are telling TS to trust us
Always prefer
unknownoverany. It forces you to write defensive code and validate data before operating on it.