TypeScript条件类型 #

一、条件类型基础 #

1.1 什么是条件类型 #

条件类型根据条件选择两个类型之一,类似于JavaScript的三元运算符。

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

type A = IsString<string>;
type B = IsString<number>;

1.2 基本语法 #

typescript
type Conditional<T> = T extends U ? X : Y;
  • 如果T可以赋值给U,则类型为X
  • 否则类型为Y

1.3 简单示例 #

typescript
type IsNumber<T> = T extends number ? 'yes' : 'no';

type A = IsNumber<number>;
type B = IsNumber<string>;
type C = IsNumber<number | string>;

二、条件类型分发 #

2.1 什么是分发 #

当条件类型作用于联合类型时,会自动分发到每个成员:

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

type StrArr = ToArray<string>;
type NumArr = ToArray<number>;
type Mixed = ToArray<string | number>;

2.2 分发过程 #

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

type Result = ToArray<string | number>;

type Result = ToArray<string> | ToArray<number>;

2.3 避免分发 #

使用元组类型避免分发:

typescript
type ToArrayNonDist<T> = [T] extends [any] ? T[] : never;

type Result = ToArrayNonDist<string | number>;

2.4 实际应用 #

typescript
type NonNullable<T> = T extends null | undefined ? never : T;

type A = NonNullable<string | null | undefined>;
type B = NonNullable<null>;
type C = NonNullable<undefined>;

三、infer关键字 #

3.1 什么是infer #

infer用于在条件类型中推断类型,只能在extends子句中使用。

typescript
type UnwrapArray<T> = T extends (infer U)[] ? U : T;

type Str = UnwrapArray<string[]>;
type Num = UnwrapArray<number>;

3.2 推断数组元素类型 #

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

type A = ElementType<string[]>;
type B = ElementType<number[]>;
type C = ElementType<[string, number]>;

3.3 推断函数返回类型 #

typescript
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;

function greet(): string {
    return 'hello';
}

type R = ReturnType<typeof greet>;

3.4 推断函数参数类型 #

typescript
type Parameters<T> = T extends (...args: infer P) => any ? P : never;

function add(a: number, b: number): number {
    return a + b;
}

type Params = Parameters<typeof add>;

3.5 推断Promise值类型 #

typescript
type Awaited<T> = T extends Promise<infer U> ? U : T;

type A = Awaited<Promise<string>>;
type B = Awaited<Promise<number>>;
type C = Awaited<string>;

3.6 多个infer #

typescript
type UnwrapTuple<T> = T extends [infer A, infer B] ? [A, B] : never;

type Result = UnwrapTuple<[string, number]>;

四、内置条件类型 #

4.1 Exclude #

从类型中排除可以赋值给U的类型:

typescript
type Exclude<T, U> = T extends U ? never : T;

type A = Exclude<'a' | 'b' | 'c', 'a'>;
type B = Exclude<string | number | boolean, number>;

4.2 Extract #

提取可以赋值给U的类型:

typescript
type Extract<T, U> = T extends U ? T : never;

type A = Extract<'a' | 'b' | 'c', 'a' | 'b'>;
type B = Extract<string | number | boolean, number>;

4.3 NonNullable #

排除null和undefined:

typescript
type NonNullable<T> = T extends null | undefined ? never : T;

type A = NonNullable<string | null | undefined>;
type B = NonNullable<null>;

4.4 ReturnType #

获取函数返回类型:

typescript
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;

function fn(): string {
    return 'hello';
}

type R = ReturnType<typeof fn>;

4.5 Parameters #

获取函数参数类型:

typescript
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;

function fn(a: string, b: number): void {}

type P = Parameters<typeof fn>;

4.6 InstanceType #

获取构造函数实例类型:

typescript
type InstanceType<T extends new (...args: any) => any> = T extends new (...args: any) => infer R ? R : any;

class User {
    name = 'Alice';
}

type I = InstanceType<typeof User>;

五、高级应用 #

5.1 深层Partial #

typescript
type DeepPartial<T> = {
    [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};

interface User {
    name: string;
    address: {
        city: string;
        country: string;
    };
}

type PartialUser = DeepPartial<User>;

const user: PartialUser = {
    name: 'Alice',
    address: {
        city: 'NYC'
    }
};

5.2 深层Required #

typescript
type DeepRequired<T> = {
    [P in keyof T]-?: T[P] extends object ? DeepRequired<T[P]> : T[P];
};

5.3 深层Readonly #

typescript
type DeepReadonly<T> = {
    readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P];
};

5.4 函数重载类型 #

typescript
type Overload<T, U> = T extends {
    (a: infer A): infer R;
    (b: infer B): infer R;
} ? (a: A, b: B) => R : never;

5.5 提取数组元素 #

typescript
type ArrayElement<T> = T extends (infer E)[] ? E : never;

type A = ArrayElement<string[]>;
type B = ArrayElement<number[]>;

六、实用示例 #

6.1 类型安全的Object.keys #

typescript
type ObjectKeys<T extends object> = `${Exclude<keyof T, symbol>}`;

function getKeys<T extends object>(obj: T): ObjectKeys<T>[] {
    return Object.keys(obj) as ObjectKeys<T>[];
}

const user = { name: 'Alice', age: 25 };
const keys = getKeys(user);

6.2 提取函数类型 #

typescript
type ExtractFunction<T> = T extends (...args: any[]) => any ? T : never;

type Fn = ExtractFunction<(() => void) | string>;

6.3 类型谓词 #

typescript
type IsArray<T> = T extends any[] ? true : false;

type A = IsArray<string[]>;
type B = IsArray<string>;

七、总结 #

本章介绍了TypeScript条件类型:

条件类型基础 #

  1. 三元运算符语法
  2. 条件类型分发
  3. infer关键字

内置条件类型 #

  1. Exclude
  2. Extract
  3. NonNullable
  4. ReturnType
  5. Parameters
  6. InstanceType

最佳实践 #

  1. 使用infer推断类型
  2. 理解分发机制
  3. 创建可复用的条件类型
最后更新:2026-03-26