bugl
bugl
HomeLearnPatternsSearch
HomeLearnPatternsSearch

Loading lesson path

Learn/TypeScript/TypeScript Core
TypeScript•TypeScript Core

TypeScript Conditional Types

Understanding Conditional Types in TypeScript

Conditional types in TypeScript enable you to create types that depend on other types, similar to how if-else statements work in JavaScript.

Formula

They're a powerful feature that allows for sophisticated type transformations and type - level programming.

Key Concepts

Type-level logic

: Perform conditional checks on types

Type inference

: Extract and manipulate types using infer

Composition

: Combine with other TypeScript features

Utility types

: Build powerful type utilities

Common Use Cases

Type-safe function overloading

API response type transformations

Complex type validations

Building reusable type utilities

Advanced type inference

Basic Conditional Type Syntax

Conditional types use the form

T extends U ? X : Y, which means: "if type T extends (or is assignable to) type U, use type X, otherwise use type Y ".

Example type IsString<T> = T extends string ? true : false;

// Usage examples type Result1 = IsString<string>;  // true type Result2 = IsString<number>;  // false type Result3 = IsString<"hello">; // true (literal types extend their base types)

Formula

// We can use this with variables too let a: IsString < string >; // a has type 'true'
let b: IsString<number>; // b has type 'false'

Conditional Types with Unions

Distributive Conditional Types

Conditional types are particularly useful with union types, where they're automatically distributed over union members:

Example type ToArray<T> = T extends any ? T[] : never;

// When used with a union type, it applies to each member of the union type StringOrNumberArray = ToArray<string | number>;

Formula

// This becomes ToArray < string > | ToArray < number >

// Which becomes string[] | number[]

Formula

// We can also extract specific types from a union type ExtractString < T > = T extends string ? T : never;
type StringsOnly = ExtractString<string | number | boolean | "hello">;
// Result: string | "hello"

Type Inference with infer

Extracting Types from Complex Structures

The infer keyword allows you to declare a type variable within the condition part of a conditional type and then use it in the true branch of the condition:

Example

Formula

// Extract the return type of a function type type ReturnType < T > = T extends (...args: any[]) => infer R ? R : never;
// Examples function greet() { return "Hello, world!"; }
function getNumber() { return 42; }
type GreetReturnType = ReturnType<typeof greet>;   // string type NumberReturnType = ReturnType<typeof getNumber>; // number

Formula

// Extract element type from array type ElementType < T > = T extends (infer U)[] ? U : never;
type NumberArrayElement = ElementType<number[]>; // number type StringArrayElement = ElementType<string[]>; // string

Built-in Conditional Types

Standard Library Utilities

Formula

TypeScript includes several built - in conditional types in its standard library:

Example

Formula

// Extract < T, U > - Extracts types from T that are assignable to U
type OnlyStrings = Extract<string | number | boolean, string>; // string

Formula

// Exclude < T, U > - Excludes types from T that are assignable to U
type NoStrings = Exclude<string | number | boolean, string>; // number | boolean

Formula

// NonNullable < T > - Removes null and undefined from T
type NotNull = NonNullable<string | null | undefined>; // string
// Parameters<T> - Extracts parameter types from a function type type Params = Parameters<(a: string, b: number) => void>; // [string, number]
// ReturnType<T> - Extracts the return type from a function type type Return = ReturnType<() => string>; // string

Advanced Patterns and Techniques

Recursive Conditional Types

Conditional types can be used recursively to create complex type transformations:

Previous

TypeScript Type Guards

Next

TypeScript Mapped Types