Start Coding

Topics

Conditional Types in TypeScript

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.

Basic Syntax

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'.

Use Cases

1. Type Inference

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

2. Filtering Union Types

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

Advanced Techniques

Distributive Conditional Types

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[]

Mapped Types with Conditional Types

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>);

Best Practices

  • Use conditional types to create flexible, reusable type definitions.
  • Combine with generics for maximum flexibility.
  • Leverage the infer keyword for type inference in complex scenarios.
  • Be cautious with nested conditional types, as they can become hard to read and maintain.

Conclusion

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.