T extends never
1. What never is
The never type means:
"a value that can never exist".
Examples:
function fail(): never {
throw new Error("Error!");
}never is a subtype of all types, but nothing is a subtype of never,
except never itself.
2. What T extends never ? X : Y does
This is a conditional type, which can be read as:
"If type
Tisnever, returnX, otherwise returnY."
Example:
type Check<T> = T extends never ? "YES" : "NO";
type A = Check<never>; // "YES"
type B = Check<string>; // "NO"
type C = Check<any>; // "NO"A returns "YES", because T is indeed never.
3. But! A quirk: conditional types distribute over union types
If T is a union (A | B | C),
TypeScript applies the condition separately to each member.
type Example<T> = T extends never ? "Y" : "N";
type R1 = Example<string | never | number>;
// Step by step:
// string → "N"
// never → "Y"
// number → "N"
// R1 = "N" | "Y" | "N" → "N" | "Y"Even if never is present inside the union,
it "dissolves" (has no effect), and the result stays "N" | "Y".
4. Why never sometimes "disappears" in unions
never is an "absorbing" element of unions:
string | never // → string
number | never // → numberSo when substituted into T extends ...,
if T doesn't exist at all (for example, after filtering),
the result is not distributed and can turn into never.
Example 1: checking for an "empty" type
type IsNever<T> = [T] extends [never] ? true : false;
type A = IsNever<never>; // true
type B = IsNever<string>; // false
type C = IsNever<any>; // falseWhy square brackets? They disable distributivity, and the check runs against the type as a whole, not against each union member.
Example 2: without brackets, the result is unexpected
type IsNeverDistributive<T> = T extends never ? true : false;
type A = IsNeverDistributive<never>; // never (!) - not trueBecause the conditional type "distributed" over an empty set (never → no members → no result).
So the result became never, not true.
Fix:
type IsNever<T> = [T] extends [never] ? true : false;Example 3: using it to filter types
type FilterNever<T> = T extends never ? never : T;
type A = FilterNever<string | never | number>;
// string | numberAll
nevervalues were "filtered out" of the union type.
Example 4: checking in conditional utilities
type SafeReturn<T> = T extends never ? "No value" : T;
type A = SafeReturn<never>; // "No value"
type B = SafeReturn<"ok">; // "ok"The mechanics, briefly
| Situation | What happens |
|---|---|
never extends never | true |
never extends anything else | true (since never is a subtype of all types) |
something extends never | false (except never itself) |
T extends never ? X : Y | Returns X only if T === never |
T extends never ? X : Y (with a union) | Distributes over each union member |
[T] extends [never] ? X : Y | Checks the whole type without distribution |
Summary
| Check | Behavior | Example |
|---|---|---|
| Simple check | T extends never ? X : Y | Check<never> → X |
| Unexpected distribution | T = never gives never, not X | IsNeverDistributive<never> → never |
| Correct check | [T] extends [never] ? X : Y | IsNever<never> → true |
| Filtering | T extends never ? never : T | Removes never from a union |
| Reason | never is an "empty set of types" | Contains no values, but is a subtype of any type |
Put simply
T extends never ? X : Yis a conditional type for checking "emptiness".- But when
T = never, it turns intoneveritself. - To correctly check "is the type
never", you need to wrap the type in a tuple:type IsNever<T> = [T] extends [never] ? true : false;
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.