Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

A conditional type is a type-level expression that selects one of two possible types based on an assignability relationship. It evaluates whether a base type satisfies a specific constraint using the extends keyword. While its syntax mirrors the JavaScript ternary operator, its mechanics rely strictly on compile-time type assignability checks rather than runtime value truthiness.
type Conditional<T, U, TrueType, FalseType> = T extends U ? TrueType : FalseType;

Evaluation Mechanics

The core mechanism relies on the extends keyword acting as a subtyping or assignability check.
  • If the type T is assignable to the type U, the expression resolves to the TrueType branch.
  • If T is not assignable to U, it resolves to the FalseType branch.
When T and U are fully known (instantiated) types, TypeScript evaluates the conditional type immediately. If T is an unresolved generic type parameter, the evaluation is deferred until the compiler possesses enough type information to resolve the assignability check.

Distributive Conditional Types

When a conditional type operates on a generic type parameter, and that parameter is a union type, the conditional type becomes distributive. This occurs exclusively when the type parameter is “naked”—meaning it is not wrapped within another type construct such as an array, tuple, or promise. During distribution, TypeScript maps the conditional operation across each constituent of the union type independently, and then unites the results.
type Distribute<T> = T extends string ? true : false;

// Evaluates as: (string extends string ? true : false) | (number extends string ? true : false)
// Resolves to: true | false
type DistributiveResult = Distribute<string | number>; 
A critical edge case in distribution occurs when the naked type parameter is never. Because TypeScript treats never as an empty union, a distributive conditional type distributes zero times. The expression immediately resolves to never, bypassing the extends check entirely.
// Resolves to: never (the condition 'never extends string' is not evaluated)
type NeverResult = Distribute<never>;
To prevent distribution, both sides of the extends clause must be wrapped in a tuple. This forces the compiler to evaluate the union as a single, cohesive type rather than distributing over its constituents. It also prevents never from short-circuiting the evaluation.
type NonDistributive<T> = [T] extends [string] ? true : false;

// Resolves to: false (because the union 'string | number' is not strictly assignable to 'string')
type NonDistributiveResult = NonDistributive<string | number>;

// Resolves to: true (because [never] is assignable to [string])
type NonDistributiveNever = NonDistributive<never>;

Pattern Matching with infer

Conditional types support structural type extraction via the infer keyword. When used within the extends clause, infer introduces a declarative type variable that the compiler attempts to deduce based on the structure of the type being evaluated. If the assignability check succeeds, the inferred type variable becomes available exclusively within the TrueType branch.
type ExtractElement<T> = T extends (infer U)[] ? U : T;

// 'infer U' matches the element type of the array.
// Resolves to: string
type Extracted = ExtractElement<string[]>; 
Multiple infer declarations can be utilized within a single conditional type to extract multiple structural components simultaneously, provided the base type matches the complex signature defined in the extends clause.
Master TypeScript with Deep Grasping Methodology!Learn More