`void`, `never`, `unknown`, `any` — Pick the Right One
Special Types
Four special types — each with a specific meaning. Learn what each one means, and pick `unknown` over `any` almost always.
What you'll learn
- Tell `void` from `undefined`
- Use `unknown` instead of `any`
- Recognize where `never` shows up
Four “special” types each play a different role. Knowing when to reach for each is half of writing good TS.
void — Function Returns Nothing
function log(msg: string): void {
console.log(msg);
} void says “this function isn’t expected to return a useful
value”. You can still return from the function — just not a
value that callers should use.
A callback typed as () => void can return anything; callers
just won’t see it.
never — A Value That Never Happens
function fail(msg: string): never {
throw new Error(msg);
} A function that always throws (or loops forever) returns never.
It also shows up in exhaustive switch statements (covered in
discriminated unions).
never is “no value will EVER satisfy this type”. It’s the bottom
type — assignable to every other type, but only never itself is
assignable to never.
unknown — Safe any
function parse(json: string): unknown {
return JSON.parse(json);
}
const data = parse(text);
data.foo;
// ~~~ Object is of type 'unknown'. unknown is “I don’t know what this is — and TypeScript should
force me to check before using it.” Compare to any, which
disables type checking entirely.
To use unknown, narrow it:
if (typeof data === "string") {
data.toUpperCase(); // ✓ narrowed to string
}
if (typeof data === "object" && data !== null && "name" in data) {
// data is now { name: unknown }
} unknown is what any should have been.
any — Type Checking Off
let x: any = "hi";
x = 42;
x.toUpperCase(); // ✓ — TS doesn't check
x.foo.bar.baz(); // ✓ — TS doesn't check
x(); // ✓ — TS doesn't check any opts out of type checking. The escape hatch — useful when
gradually adopting TS or when types just don’t exist.
null and undefined
With strictNullChecks (part of strict), these are their own
types:
let x: string = null;
// ~ Type 'null' is not assignable to type 'string'.
let y: string | null = null; // ✓ allow it explicitly The strict null check is one of the most important TS features. Always leave it on.
Quick Reference
| Type | When to use |
|---|---|
void | A function that returns nothing useful |
never | A function that never returns (throws / infinite) |
unknown | A value of an unknown type — must check before using |
any | Escape hatch — turns off type checking |
null | Explicitly missing value |
undefined | Uninitialized / missing optional property |
Up Next
Narrowing — how TS figures out what type something is at each point in your code.
Narrowing →