Conditional types are a powerful feature in TypeScript that allow you to create flexible and reusable type definitions based on conditions. They enable you to express complex type relationships and perform type transformations depending on the input types.
The syntax for conditional types resembles a ternary operator in JavaScript:
type Result<T> = T extends string ? 'string' : 'not string';
In this example, if T extends (is assignable to) string, the type will be 'string'; otherwise, it will be 'not string'.
Conditional types are often used with the infer
keyword to extract types from other types:
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
function greet(name: string): string {
return `Hello, ${name}!`;
}
type GreetReturn = ReturnType<typeof greet>; // string
You can use conditional types to filter union types:
type NonNullable<T> = T extends null | undefined ? never : T;
type Types = string | number | null | undefined;
type FilteredTypes = NonNullable<Types>; // string | number
When used with a union type, conditional types become distributive:
type ToArray<T> = T extends any ? T[] : never;
type Result = ToArray<string | number>; // string[] | number[]
Combining mapped types with conditional types allows for powerful type transformations:
type Nullable<T> = { [K in keyof T]: T[K] | null };
type Partial<T> = { [K in keyof T]?: T[K] };
type MakeNullableOrPartial<T, MakeNullable extends boolean> = {
[K in keyof T]: MakeNullable extends true ? T[K] | null : T[K];
} & (MakeNullable extends true ? {} : Partial<T>);
infer
keyword for type inference in complex scenarios.Conditional types in TypeScript provide a powerful way to create dynamic and flexible type definitions. They enable advanced type manipulation, making your code more expressive and type-safe. As you become more comfortable with conditional types, you'll find them invaluable for solving complex typing challenges in your TypeScript projects.
For more advanced type manipulations, consider exploring mapped types and utility types in TypeScript.