TypeScript 高级类型

TypeScript 中的条件类型、函数重载、可辨识联合、类型守卫、infer 和映射类型等高级类型能力。

#tech / dev #resource / typescript #type / concept #status / growing

[!info] related notes

TypeScript 高级类型

一句话定义

TypeScript 高级类型是泛型、条件类型、函数重载、可辨识联合、类型守卫、infer 和映射类型等能力的统称,它们让类型系统能表达更复杂的输入输出关系。

核心机制 / 工作原理

1. 泛型 Generics

在定义时不指定具体类型,使用时再确定。

function identity<T>(value: T): T {
  return value;
}

const num = identity(42);       // 推导为 number
const str = identity('hello');  // 推导为 string

泛型常用于封装返回值类型不确定的函数,如 Promise<Result<T>>

2. 条件类型 Conditional Types

type IsString<T> = T extends string ? 'yes' : 'no';

type A = IsString<string>;  // 'yes'
type B = IsString<number>;  // 'no'

配合 infer 可以提取类型:

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

3. 函数重载 Function Overloads

当同一个函数根据参数类型返回不同结构时使用。

function parse(value: string): { type: 'text'; value: string };
function parse(value: number): { type: 'number'; value: number };
function parse(value: string | number) {
  if (typeof value === 'string') {
    return { type: 'text', value };
  }
  return { type: 'number', value };
}

const r1 = parse('hi');  // { type: 'text'; value: string }
const r2 = parse(42);    // { type: 'number'; value: number }

4. 可辨识联合 Discriminated Union

用一个共同字段区分不同类型,配合类型守卫收窄。

type Shape =
  | { kind: 'circle'; radius: number }
  | { kind: 'rect'; width: number; height: number };

function area(s: Shape): number {
  switch (s.kind) {
    case 'circle': return Math.PI * s.radius ** 2;
    case 'rect':   return s.width * s.height;
  }
}

5. 类型守卫 Type Guards

function isString(val: unknown): val is string {
  return typeof val === 'string';
}

function example(val: string | number) {
  if (isString(val)) {
    val.toUpperCase(); // TS 知道这里是 string
  }
}

内置守卫:typeofinstanceofin、判空。

6. infer 关键字

在条件类型中声明一个待推导的类型变量。

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

7. 泛型约束

function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

最小例子 / 最小场景

根据查询类型返回不同结构:

type QueryType = 'user' | 'order';

type QueryResult<T extends QueryType> =
  T extends 'user'  ? { id: string; name: string } :
  T extends 'order' ? { id: string; amount: number } :
  never;

function query<T extends QueryType>(type: T): QueryResult<T> {
  if (type === 'user') {
    return { id: 'u1', name: 'Arlon' } as QueryResult<T>;
  }
  return { id: 'o1', amount: 100 } as QueryResult<T>;
}

const user = query('user');  // { id: string; name: string }
const order = query('order'); // { id: string; amount: number }

边界与常见误解

  • as type 断言不是类型安全的保障,是绕过类型系统的手段;应尽量用泛型和条件类型让 TS 自动推导
  • 函数重载的实现签名(最后一个签名)不对外可见,只用于内部实现
  • 条件类型在分布式联合类型上会展开:Foo<A | B> 等于 Foo<A> | Foo<B>
  • infer 只能在 extends 子句中使用
创建于 2026/5/29 更新于 2026/5/29