This site uses tracking technologies. You may opt in or opt out of the use of these technologies.

Back to Typescript

Typescript Conditional Types: Use extends, infer, and keyof to create conditional logic in types.

TypeScript's Conditional Types provide a way to perform type-level computations using a ternary-like syntax.

By combining extends, infer, and keyof, we can express complex type logic. Here's a breakdown:

1. Basic Conditional Types Syntax typescript

1T extends U ? X : Y
2
  • If T is assignable to U, the type resolves to X; otherwise, it resolves to Y.

2. Using extends in Conditional Types

You can check if one type extends another:

1type IsString<T> = T extends string ? true : false;
2
3type Test1 = IsString<string>; // true
4type Test2 = IsString<number>; // false
5

3. Using infer to Extract Types

infer allows you to extract types in conditional types, often within generic contexts like functions or arrays.

Example: Extract Return Type of a Function

1type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
2
3type Fn = (x: number) => string;
4type Result = ReturnType<Fn>; // string
5

Example: Extract Array Element Type

1type ElementType<T> = T extends (infer U)[] ? U : never;
2
3type ArrayOfNumbers = number[];
4type Result = ElementType<ArrayOfNumbers>; // number
5

4. Using keyof with Conditional Types

keyof extracts the keys of a type, useful when working with object types.

Example: Conditional Type to Check for a Specific Property

1type HasName<T> = 'name' extends keyof T ? true : false;
2
3type ObjWithName = { name: string; age: number };
4type ObjWithoutName = { age: number };
5
6type Test1 = HasName<ObjWithName>; // true
7type Test2 = HasName<ObjWithoutName>; // false
8

5. Combining extends, infer, and keyof

You can combine all three to create powerful type utilities.

Example: Extract the Type of a Specific Property

1type PropertyType<T, K extends keyof T> = T[K];
2
3type Person = { name: string; age: number };
4type NameType = PropertyType<Person, 'name'>; // string
5

Example: Deeply Nested Return Type Extraction

1type DeepReturnType<T> =
2 T extends (...args: any[]) => infer R
3 ? R extends (...args: any[]) => any
4 ? DeepReturnType<R>
5 : R
6 : never;
7
8type Fn1 = () => () => number;
9type Fn2 = () => () => () => string;
10
11type Result1 = DeepReturnType<Fn1>; // number
12type Result2 = DeepReturnType<Fn2>; // string
13

Summary

By combining extends, infer, and keyof in TypeScript conditional types:

  • extends checks subtype relations.

  • infer extracts and infers types.

  • keyof works with keys of object types.

These tools enable you to build highly flexible, type-safe utilities for complex type manipulations.