Oct 25, 2025

TypeScript any vs unknown: Key Differences and Best Practices

Working with dynamic or external data in TypeScript can be tricky especially when you’re not sure what shape that data will take. This is where the any and unknown types come in, each handling uncertainty in a different way. While any acts as a “turn off type safety” switch, letting you do anything without checks, unknown forces you to validate and narrow types before using them.


Understanding the key differences between these two special types will help you write much safer, more predictable, and maintainable TypeScript code, especially when handling API responses or user input.


TypeScript any vs unknown: Key Differences and Best Practices


What is 'any' in TypeScript?


The any type in TypeScript is an “escape hatch” that turns off type checking for a variable. Once you use any, you can assign any value and perform any action on that value, and the compiler won’t catch errors, even deeply unsafe actions. It’s like telling TypeScript, “Trust me, I know what I’m doing!”.

Example:


let value: any = "Hello";
value = 42;
value = { greet: "Hi" };
console.log(value.nonExistentMethod()); // No error at compile time, will crash at runtime!


What is 'unknown' in TypeScript?


The unknown type is a safer alternative to any. Like any, it allows assignment of any value but you can’t perform arbitrary operations on it until you explicitly check or assert its type. TypeScript forces you to prove what the value is before using it.


let result: unknown = "Hello";
if (typeof result === "string") {
  console.log(result.toUpperCase()); // ✅ Safe, type checked
}

Trying to use unknown directly triggers a compile-time error!


Type Narrowing for 'unknown' (typeof, instanceof, custom guards)


Before using an unknown value, narrow its type:

if (typeof input === "string") { /* ... */ }
if (input instanceof Array) { /* ... */ }
function isUser(val: unknown): val is User { return typeof val === "object" && val !== null && "email" in val; }


How TypeScript Treats Type Checking for 'any' vs 'unknown'


  • any: No type checks; compiler lets anything through.
  • unknown: The compiler requires type narrowing or assertion before use, enforcing safety.

Why 'unknown' is Safer than 'any'


'unknown' forces you to check or narrow the type before every operation, reducing runtime bugs. By using 'unknown', you keep TypeScript’s guarantees, making your code easier to debug, refactor, and scale safely.


When to Use 'unknown' Instead of 'any'


Use unknown for external data with unpredictable shape API responses, user input, deserialized JSON, so you’re required to validate before using it.

Example:


function handleApiResponse(data: unknown) {
  if (typeof data === "object" && data !== null && "success" in data) {
    // Safe to proceed!
  }
}


When 'any' Is Necessary (Limiting Scope)


Sometimes any is needed rapid prototyping, using broken external libraries, or testing. Always restrict its usage to small scopes, and migrate to unknown or concrete types quickly.


Common Mistakes Developers Make with 'any'


  • Overusing any leads to silent bugs and runtime crashes.
  • Assigning any too early disables TypeScript for the rest of the code.
  • Using any for APIs, user data, or third-party packages instead of validating types.

Real-World Use Cases for 'unknown'


Check some Real World use cases for type unknown below-

1- Handling API Response Data with 'unknown'


Always type your API responses with unknown first, and check their shape:


function getData(): Promise<unknown> { /* ... */ }
getData().then(response => {
  if (typeof response === "object" && response !== null) { /*...*/ }
});


2- Working with Dynamic User Input Safely Using 'unknown'


If you get dynamic input from forms, treat it as unknown:


function processInput(input: unknown) {
  if (typeof input === "string") { /* ... */ }
}


3- Validating Unknown JSON Data



function validateJSON(val: unknown): val is User {
  return typeof val === "object" && val !== null && "email" in val;
}


Migrating from 'any' to 'unknown': Step-by-Step


  • Change your variable’s type from any to unknown.
  • Add type checks wherever you use that variable.
  • Use custom type guards as needed.
  • Refactor dependent code to ensure strict safety.

TypeScript Best Practices: Avoid 'any', Embrace 'unknown'


  • Default to unknown for untyped data.
  • Only use any for prototyping, legacy code, or unavoidable hacks.
  • Always narrow unknown to concrete types before use.
  • Leverage custom guards for advanced validation.

Summary


The any type gives you total freedom but sacrifices all safety making TypeScript act like plain JavaScript, with all its potential runtime surprises. In contrast, unknown is a safer alternative, allowing you the flexibility to receive any value while ensuring you still leverage TypeScript’s powerful compile-time checks.

By embracing unknown, you push yourself and your team to narrow types and validate assumptions, leading to fewer bugs and more robust applications. Whenever you’re dealing with unpredictable or external data, reach for unknown over any your future code (and coworkers) will thank you.


EmoticonEmoticon