Open In App

TypeScript Conditional Types

Last Updated : 24 Jan, 2025
Summarize
Comments
Improve
Suggest changes
Like Article
Like
Share
Report
News Follow

In TypeScript, conditional types enable developers to create types that depend on a condition, allowing for more dynamic and flexible type definitions.

  • They follow the syntax T extends U ? X : Y, meaning if type T is assignable to type U, the type resolves to X; otherwise, it resolves to Y.
  • Conditional types are particularly useful for creating utility types and for advanced type manipulations, enhancing code reusability and type safety.
type IsString<T> = T extends string ? 'Yes' : 'No';

type Test1 = IsString<string>;
type Test2 = IsString<number>;

console.log('Test1:', 'Yes');
console.log('Test2:', 'No');
  • The IsString type alias uses a conditional type to check if a type T extends the string.
  • If T is assignable to string, it resolves to 'Yes'; otherwise, it resolves to 'No'.
  • Test1 is evaluated as 'Yes' because the string extends the string.
  • Test2 is evaluated as 'No' because the number does not extend the string.

Output:

Test1: Yes
Test2: No
type Num<T> = T extends number[] ? number 
    : (T extends string[] ? string : never)
    
// Return num
const num: Num<number[]> = 4;

// Return invalid
const stringnum: Num<number> = "7";

console.log(num, stringnum);

Conditional Type Constraints

Conditional type constraints allow defining constraints on generic types within conditional types, enabling dynamic and precise type handling.

type CheckNum<T> = T extends number ? T : never;

type NumbersOnly<T extends any[]> = {
  [K in keyof T]: CheckNum<T[K]>;
};

const num: NumbersOnly<[4, 5, 6, 8]> = [4, 5, 6, 8];
const invalid: NumbersOnly<[4, 6, "7"]> = [4, 6, "7"];
  • CheckNum<T> ensures only numbers are retained; other types resolve to never.
  • NumbersOnly<T> applies CheckNum to each array element, filtering non-numbers.

Output:

Type '"7"' is not assignable to type 'never'.

Inferring Within Conditional Types

This feature extracts and utilizes types within a conditional type definition, enabling precise transformations.

type ElementType<T> = T extends (infer U)[] ? U : never;

const numbers: number[] = [1, 2, 3];
const element: ElementType<typeof numbers> = numbers[0];
const invalidElement: ElementType<typeof numbers> = "string";
  • ElementType<T> extracts element types from arrays using the infer keyword.
  • element correctly resolves to number; assigning a string is invalid.

Output:

Type 'string' is not assignable to type 'number'.

Distributive Conditional Types

These types distribute over unions, applying conditional logic to each union member individually.

type Colors = 'red' | 'blue' | 'green';

type ColorClassMap = {
  red: 'danger';
  blue: 'primary';
  green: 'success';
};

type MapColorsToClasses<T extends string> = T extends keyof ColorClassMap
  ? { [K in T]: ColorClassMap[T] }
  : never;

const redClass: MapColorsToClasses<Colors> = { red: 'danger' };
const invalidClass: MapColorsToClasses<Colors> = { yellow: 'warning' };
  • MapColorsToClasses<T> checks if T matches a key in ColorClassMap, mapping it accordingly.
  • Invalid colors like 'yellow' are rejected because they do not exist in ColorClassMap.

Output:

Type '{ yellow: "warning"; }' is not assignable to type 'never'.

Best Practices of Using TypeScript Conditional Types

  • Use conditional types to create flexible, reusable type definitions.
  • Combine conditional types with generics for enhanced adaptability.
  • Utilize the infer keyword for type inference in complex scenarios.

TypeScript Conditional Types - FAQs

How do you write a basic conditional type in TypeScript?

A basic conditional type uses the syntax T extends U ? X : Y, where if T extends U, the type resolves to X; otherwise, it resolves to Y.

What is the purpose of the extends keyword in conditional types?

In conditional types, the extends keyword checks if one type is assignable to another, determining which type branch (true or false) to select.

Can conditional types be nested in TypeScript?

Yes, conditional types can be nested to handle complex type logic, allowing for multiple conditions or layered type transformations.

What are distributive conditional types in TypeScript?

Distributive conditional types automatically distribute over union types, applying the conditional logic to each member of the union separately.

How do conditional types work with union and intersection types?

Conditional types distribute over union types, applying the condition to each union member, and can be used with intersection types to create complex type relationships.


Similar Reads

three90RightbarBannerImg