any vs unknown vs never in TypeScript

A
Author
26 Apr, 2026 1 min read 396 views

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.

Leave a comment

Comments are reviewed before they appear.