Skip to content

Commit 998721a

Browse files
Basarat Ali SyedBasarat Ali Syed
authored andcommitted
never closes basarat#113
1 parent 1976301 commit 998721a

File tree

2 files changed

+65
-0
lines changed

2 files changed

+65
-0
lines changed

SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
* [Readonly](docs/types/readonly.md)
4848
* [Type Inference](docs/types/type-inference.md)
4949
* [Type Compatibility](docs/types/typeCompatibility.md)
50+
* [Never Type](docs/types/never.md)
5051
* [Discriminated Unions](docs/types/discriminated-unions.md)
5152
* [JSX](docs/jsx/tsx.md)
5253
* [TIPs](docs/tips/main.md)

docs/types/never.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Never
2+
3+
> Never ever ever (joke)
4+
5+
Programming language design does have a concept of *bottom* type that is a **natural** outcome as soon as you do *code flow analysis*. TypeScript does *code flow analysis* (😎) and so it needs to reliably represent stuff that might never happen.
6+
7+
The `never` type is used in TypeScript to denote this *bottom* type. Cases when it occurs naturally:
8+
9+
* A function never returns (e.g. if the function body has `while(true){}`)
10+
* A function always throws (e.g. in `function foo(){throw new Error('Not Implemented')}` the return type of `foo` is `never`.
11+
12+
Of course you can use this annotation your self as well
13+
14+
```ts
15+
let foo: never; // Okay
16+
```
17+
18+
However `never` *can only ever be assigned to another never*. e.g.
19+
20+
```ts
21+
let foo: never = 123; // Error: Type number is not assignable to number
22+
23+
// Okay as the function's return type is `never`
24+
let bar: never = (() => { throw new Error('Throw my hands in the air like I just dont care') })();
25+
```
26+
27+
And this property takes it to our use cases.
28+
29+
# Use case: Exhaustive Checks
30+
31+
You can call never functions in a never context
32+
33+
```
34+
function foo(x: string | number): boolean {
35+
if (typeof x === "string") {
36+
return true;
37+
} else if (typeof x === "number") {
38+
return false;
39+
}
40+
41+
// Without a never type we would error :
42+
// - Not all code paths return a value (strict null checks)
43+
// - Or Unreachable code detected
44+
// But because typescript understands that `fail` function returns `never`
45+
// It can allow you to call it as you might be using it for runtime safety / exhaustive checks.
46+
fail("Unexhaustive!");
47+
}
48+
49+
function fail(message: string) { throw new Error(message); }
50+
```
51+
52+
And because `never` is only assignable to another `never` you can use it for *compile time* exhaustive checks as well. This is covered in the [*discriminated union* section](./discriminated-unions.md).
53+
54+
# Confusion with `void`
55+
56+
As soon as someone tells you that `never` is returned when a function never exits gracefully you intutively want to think of it as the same as `void` However `void` is a Unit. `never` is a falsum.
57+
58+
A function that *returns* nothing returns a Unit `void`. However a function *that never returns* (or always throws) returns `never`. `void` is something that can be assigned (without `strictNullChecking`) but `never` can `never` be assigned to anything other than `never`.
59+
60+
<!--
61+
PR: https://github.com/Microsoft/TypeScript/pull/8652
62+
Issue : https://github.com/Microsoft/TypeScript/issues/3076
63+
Concept : https://en.wikipedia.org/wiki/Bottom_type
64+
-->

0 commit comments

Comments
 (0)