← 返回导航

条件类型基础

工具类型 · 中级

场景说明

条件类型(Conditional Types)是 TypeScript 类型系统的核心能力之一,语法为 T extends U ? X : Y。它让你可以根据类型关系来决定最终的类型,配合 infer 关键字可以提取类型中的子类型。条件类型是实现 Pick、Exclude、ReturnType 等内置工具类型的底层机制。

完整代码


      
// 条件类型基础:T extends U ? X : Y

// 1. 基础语法
type IsString<T> = T extends string ? 'yes' : 'no';
type A = IsString<string>;   // 'yes'
type B = IsString<number>;   // 'no'

// 2. 分发条件类型(Distributive Conditional Types)
// 当 T 是联合类型时,条件类型会分发到每个成员
type ToArray<T> = T extends any ? T[] : never;
type C = ToArray<string | number>;  // string[] | number[]
// 等价于:ToArray<string> | ToArray<number>

// 3. 阻止分发(用元组包裹)
type NoDistribute<T> = [T] extends [any] ? T[] : never;
type D = NoDistribute<string | number>;  // (string | number)[]

// 4. infer 关键字 -- 在条件类型中提取类型
// 提取数组元素类型
type ArrayItem<T> = T extends (infer U)[] ? U : never;
type Item = ArrayItem<string[]>;  // string

// 提取函数返回值类型
type MyReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
type Fn = () => string;
type Ret = MyReturnType<Fn>;  // string

// 提取 Promise 内层类型
type UnwrapPromise<T> = T extends Promise<infer V> ? V : T;
type P = UnwrapPromise<Promise<number>>;  // number

// 5. 实战:根据条件返回不同 Props 类型
type ButtonProps<Variant extends 'primary' | 'danger'> =
  Variant extends 'primary'
    ? { variant: 'primary'; color: string; size: number }
    : { variant: 'danger'; confirmText: string; size: number };

type PrimaryBtn = ButtonProps<'primary'>;
// { variant: 'primary'; color: string; size: number }
type DangerBtn = ButtonProps<'danger'>;
// { variant: 'danger'; confirmText: string; size: number }

关键点解析

使用示例与类型推导


      
// 实战:条件类型实现 API 响应类型映射

interface User { id: number; name: string; }
interface Order { id: number; amount: number; }

type ApiEndpoint = '/api/users' | '/api/orders' | '/api/health';

// 根据 URL 推导响应数据类型
type ApiResponse<Url extends string> =
  Url extends '/api/users'
    ? User[]
    : Url extends '/api/orders'
      ? Order[]
      : string;  // 默认返回类型

type UsersData = ApiResponse<'/api/users'>;   // User[]
type OrdersData = ApiResponse<'/api/orders'>;  // Order[]
type HealthData = ApiResponse<'/api/health'>;  // string
在 Playground 中尝试