Conditional Types & infer
debt(d5/e3/b3/t7)
Closest to 'specialist tool catches it' (d5). The detection_hints list TypeScript's own type checker and ESLint as tools. Misuse of conditional types (e.g., wrong distributivity assumptions, infinite recursion, using 'any' where conditional types would narrow correctly) is caught by the TypeScript compiler — a specialist type-checking tool — not by a standard linter alone. Syntax errors are caught instantly, but semantic misuse (e.g., distributivity surprises producing 'boolean' instead of 'true') surfaces only under TypeScript's type analysis, placing it squarely at d5.
Closest to 'simple parameterised fix' (e3). The quick_fix describes replacing patterns with 'T extends U ? X : Y' or adding 'infer' keyword, which is a targeted refactor within one component or type definition. Common mistakes like forgetting infer or mishandling distributivity typically require editing a type definition and its usages in one area — more than a one-liner but not cross-cutting. This fits e3.
Closest to 'localised tax' (b3). Conditional types apply to web and cli contexts but are confined to type-level code in TypeScript. A poorly written conditional type imposes a tax on maintainers who need to understand it, but the impact is localised to the type definitions and the functions/components using them. The rest of the codebase is largely unaffected unless the type is deeply shared.
Closest to 'serious trap' (t7). The misconception field notes that developers think conditional types are impractical, but the deeper trap captured in common_mistakes is distributivity: 'T extends string ? true : false' where T = string | number gives 'boolean' not 'true'. This contradicts how developers expect type-level conditionals to behave (analogous to value-level ternaries), and it contradicts the non-distributive behaviour of overloads in other systems. Infinite recursion is a secondary serious trap. Together these score t7.
Also Known As
TL;DR
Explanation
Conditional types: T extends Condition ? TrueType : FalseType. Distributive conditional types: when T is a union, the condition distributes over each member. The infer keyword captures a type variable within the extends clause: T extends Promise<infer U> ? U : never extracts the resolved type of a Promise. Built-in TypeScript utilities using conditional types: ReturnType<T>, Parameters<T>, InstanceType<T>, Awaited<T>. Essential for building type utilities that work with generic type shapes.
Common Misconception
Why It Matters
Common Mistakes
- Forgetting distributivity — T extends string ? true : false where T = string | number gives boolean, not true.
- Infinite type recursion — conditional types can recurse; TypeScript limits depth.
- Using conditional types where generics or overloads are cleaner.
- Not using infer when extracting nested types — manual type indexing is error-prone.
Code Examples
// Manual return type extraction — not generic:
type StringFuncReturn = string;
type NumberFuncReturn = number;
// Need separate type for every function signature
// Conditional type with infer — works for any function:
type ReturnType<T extends (...args: any) => any> =
T extends (...args: any) => infer R ? R : never;
// Unwrap Promise:
type Awaited<T> = T extends Promise<infer U> ? Awaited<U> : T;
// Extract array element type:
type ElementType<T> = T extends (infer U)[] ? U : never;
type A = ElementType<string[]>; // string
type B = Awaited<Promise<number>>; // number
// Distributive:
type NonNullable<T> = T extends null | undefined ? never : T;
type C = NonNullable<string | null | undefined>; // string