One way to think of a type is as a set of all the values that are assignable to it. So boolean
can be thought of as {true
, false
}, the set containing just those two values. And string
can be thought of as the (essentially) infinite set containing every possible string
value.
In TypeScript, never
is the bottom type. It has no values. If you have a JavaScript value and you ask "is this a value of type never
?" then the answer is "no". In terms of sets, never
can be thought of as ?, the
empty set.
In the mapping from types to sets-of-values, the intersection operation in TypeScript (&
) can be thought of as the set intersection operation (∩). If you have sets A and B, then A∩B is the set of exactly the objects which are members of both A and B. For any set A, the intersection A∩? with the empty set is just the empty set ?. There are no elements in both A and the empty set, since there are no elements in the empty set at all. Back in TypeScript types, this means A & never
becomes never
for any type A
. It would be valid if the TypeScript compiler just left string & never
as string & never
, but in fact it goes ahead and reduces it to never
automatically, since the latter representation is simpler.
On the flip side: in the mapping from types to sets-of-values, the union operation in TypeScript (|
) can be thought of as the set union operation (∪). If you have sets A and B, then A∪B is the set of exactly the objects which are members of either A or B (this is an inclusive or). For any set A, the union A∪? with the empty set is just the A. The union contains all the elements of A and all the elements of the empty set. Since there are no elements of the empty set, that's just "all the elements of A". Back in TypeScript types, this means A | never
becomes A
for any type A
. It would be valid if the TypeScript compiler just left string | never
as string | never
, but in fact it goes ahead and reduces it to string
automatically, since the latter representation is simpler.
So that's the basic explanation. There are other analogies, such as boolean logic propositions like "this element is a member of this type" which is always FALSE for the never
type, leading to things like A ∧ FALSE = FALSE and A ∨ FALSE = A. Or like arithmetic, where the analogy isn't exact, but intersection looks like multiplication and union looks like addition (this analogy becomes exact for pairs instead of intersection and discriminated unions instead of regular unions) and the never
type is 0. But hopefully this gives enough intuition about why the compiler behaves this way.
Note that there's also a top type in TypeScript called unknown
which behaves exactly as the dual to never
in that A & unknown = A
and A | unknown = unknown
and has the dual analog in set theory (the universal set/class). But you didn't ask about that and this answer is already long enough as it is.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…