TypeScript offers two types that can hold any value: any
and unknown
. While they might seem similar, they work very differently when it comes to type safety.
The any
type effectively disables TypeScript’s type checking, treating it as “please turn off type checking for this thing.” The unknown
type is a safer alternative that requires you to check types before use.
The Problem with ‘any’
When you use any
, TypeScript stops protecting you:
function greetUser(data: any) {
return data.name.toUpperCase(); // Compiles but crashes at runtime!
}
greetUser({ age: 25 }); // Runtime error: Cannot read 'name' of undefined
Enter ‘unknown’ – The Safe Alternative
With unknown
, TypeScript forces you to check types first:
function greetUser(data: unknown) {
if (typeof data === 'object' && data && 'name' in data) {
return (data as { name: string }).name.toUpperCase();
}
return 'Unknown user';
}
greetUser({ age: 25 }); // Returns "Unknown user" - no crash!
Real-World Example: JSON Parsing
Instead of trusting JSON blindly:
// β Dangerous - no type safety
const config: any = JSON.parse(configString);
console.log(config.apiUrl.toUpperCase()); // What if apiUrl doesn't exist?
Use unknown
with validation:
// β
Safe - enforced type checking
const data: unknown = JSON.parse(configString);
if (typeof data === 'object' && data && 'apiUrl' in data) {
const config = data as { apiUrl: string };
console.log(config.apiUrl.toUpperCase()); // Safe!
}
If you don’t know what type a certain variable or function parameter is, always prefer unknown
. Think of unknown
as “I don’t know the type yet, so I need to figure it out safely” versus any
as “I don’t care about types.”
Your future self (and your teammates) will thank you when your TypeScript code actually prevents runtime errors instead of just looking like it does.
When to Use Each Type
Feature | any | unknown |
---|---|---|
Type safety | β None | β Enforced |
Can assign anything | β Yes | β Yes |
Can use without checks | β Yes | β No |
Runtime errors | π¨ Common | β Prevented |
IDE support | β Limited | β Full |
Pro tip: Enable the noImplicitAny compiler flag to catch any accidental any
usage in your codebase. Note that if you use VS Code as your editor then this is integrated automatically.
Next time you reach for any
, ask yourself: “Can I use unknown
and add proper type guards instead?” The answer is usually yes.