DAY 18 OF 30
never and exhaustiveness checking
Yesterday, in one sentence
any and unknown?Both accept any value. any switches off type checking, so you can do anything
with it. unknown keeps checking on, so you have to narrow it before you can
use it.
Did you say:
- ✓both accept any value
- ✓`any` switches off type checking
- ✓`unknown` must be narrowed before use
Interview question
any or unknown, and why?unknown. You do not know what is in the response, and unknown forces you to
narrow it before using it. any would let you read anything off it with no
checks at all.
Did you say:
- ✓`unknown`
- ✓forces you to narrow before using it
- ✓`any` would allow anything with no checks
never is the type for a value that can never exist. It represents an
impossibility.
type Impossible = string & number;
// never, because no value can be both a string and a number
You also get never from narrowingNarrowing. Once type guardsType Guard have ruled out every type in a union typeUnion Type, there is nothing left and the type
becomes never.
function describe(id: string | number) {
if (typeof id === "string") return id;
if (typeof id === "number") return id;
return id; // id has type never, all other types have been ruled out
}
An exhaustiveness check uses this to make TypeScript error when a discriminated unionDiscriminated Union gains a member you
have not handled. It works because you can only assign a value to a never once
narrowing has ruled everything else out.
type Character = { kind: "hero" } | { kind: "villain" };
function describe(character: Character) {
if (character.kind === "hero") return "saves people";
if (character.kind === "villain") return "causes trouble";
const unhandled: never = character; // ok, character is never here
return unhandled;
}
Add a third member and the assignment stops compiling.
type Character = { kind: "hero" } | { kind: "villain" } | { kind: "antihero" };
function describe(character: Character) {
if (character.kind === "hero") return "saves people";
if (character.kind === "villain") return "causes trouble";
const unhandled: never = character;
// ❌ character is not never here, "antihero" has not been handled
return unhandled;
}
That error is the point. Without it, an antihero would fall past both checks and
nothing would tell you.
Check yourself
rank on the marked line?
type Rank = "alpha" | "beta" | "omega"
function classify(rank: Rank) {
if (rank === "alpha") return
if (rank === "beta") return
if (rank === "omega") return
rank // ← here
}
All three members have been ruled out, so nothing is left and TypeScript gives you never.
never type in TypeScript?The type for a value that can never exist. TypeScript produces it when a type is impossible, such as an intersection of two types nothing can satisfy, or when narrowing has ruled out every member of a union.
Did you say:
- ✓a value that can never exist
- ✓produced by an impossible type
- ✓produced when narrowing rules out every member of a union