In TypeScript, conditional types are an advanced technique that allows selecting one of two types based on a conditional expression. It enables developers to perform type inference based on type relationships, thereby building more flexible and dynamic type systems. Extending conditional types is primarily achieved by combining and nesting generics with other conditional types to implement more complex type inference logic.
Basic Usage
The basic syntax is as follows:
typescripttype ConditionalType = T extends U ? X : Y;
Here, T extends U is a type conditional expression. If T can be assigned to U, the resulting type is X; otherwise, it is Y.
Expanded Example
Suppose we need to define a type that returns different types based on whether the input is an array or not:
typescripttype WrappedType<T> = T extends any[] ? T[number] : T;
Here, we use T extends any[] to check if T is an array type. If it is, WrappedType<T> infers to the type of the array elements (T[number]); otherwise, it directly uses T.
Using Generics
We can combine generics to extend the application of conditional types, for example, defining a utility type that dynamically generates a new type based on a given type and condition:
typescripttype FilterType<T, Condition> = T extends Condition ? T : never; // Usage example type StringOrNumber = FilterType<string | number | boolean, number | string>; // string | number
Here, FilterType filters the members of type T based on Condition, retaining only those that match.
Complex Conditional Logic
Conditional types can be nested to implement more complex type logic. For example, implementing a type that extracts the type corresponding to a given property name:
typescripttype ComplexConditional<T, K extends keyof T> = K extends any ? T[K] : never; interface Example { a: number; b: string; c: boolean; } type Result = ComplexConditional<Example, 'a' | 'b'>; // number | string
Here, ComplexConditional extracts the type corresponding to the given key K from type T.
Summary
Through these examples, we can see that conditional types are an essential tool for building powerful and flexible type systems. By extending and combining generics with nested conditions, TypeScript enables developers to construct advanced type inference and transformation mechanisms with precise control over type behavior.