Contents

Programming Fundamentals › Type Systems

any vs unknown

TypeScript's escape hatches, and why unknown is the safe one.

Also known as: any, unknown, any vs unknown TypeScript

TypeScript has two ways to say “I don’t know the type of this value”, and they behave very differently.

any: turns the checks off

let x: any = "hello";
x.toFixed(2);          // compiles! crashes at runtime
x.foo.bar.baz();       // compiles, anything goes

any removes the type checker for that value, and spreads: anything you get from an any is any too. It’s an escape hatch, used for convenience, and it silently throws away the safety you adopted TypeScript for.

unknown: the safe version

let y: unknown = JSON.parse(text);

y.name;                               // error: can't use it yet
if (typeof y === "object" && y !== null && "name" in y) {
  console.log(y.name);                // fine after narrowing
}

unknown means “could be anything, so prove what it is before using it”. You must check the type first (type narrowing), or validate it (runtime validation).

anyunknown
Assign anything to ityesyes
Use it without checkingyes (unsafe)no, compiler stops you
Spreads to other valuesyesno

Guidance

  • Use unknown for data from outside (JSON, catch (e), event payloads), and narrow or validate it.
  • Avoid any. Turn on strict mode and lint rules (no-explicit-any) to catch it.
  • If you must use any, keep it local and small, with a comment on why.
  • Casts (as Type) are also unchecked promises. A validation library is safer.
  • Many packages give you any by accident, such as a missing type definition. Install types or write a small declaration.