Skip to content

一、用法 1:泛型约束(Constraint)

  • 限制泛型的“取值范围”

1️⃣ 最基础示例

ts
function getLength<T extends { length: number }>(value: T) {
  return value.length
}
  • ✅ string / array
  • ❌ number

📌 extends = T 必须满足某个结构

2️⃣ 约束 key(超高频)

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

这里:

  • K 只能是 T 的 key
  • 否则直接报错

3️⃣ 约束函数类型

ts
type Fn<T extends (...args: any[]) => any> = T

React / Vue hooks 类型常见写法。

二、用法 2:条件类型(Conditional Types)

  • 像三元表达式一样返回不同类型

1️⃣ 基本语法

ts
T extends U ? X : Y

2️⃣ 基础示例

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

type A = IsString<'a'>    // true
type B = IsString<123>    // false

3️⃣ 常见内置工具类型

Exclude

ts
type MyExclude<T, U> = T extends U ? never : T

Extract

ts
type MyExtract<T, U> = T extends U ? T : never

4️⃣ 判断函数返回值(实战)

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

(这就是 ReturnType 的原理)

三、用法 3:分发条件类型(Distributive)

  • 条件类型 + 联合类型 = 自动拆分计算

📌 这是最容易懵的一部分

1️⃣ 看一个例子

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

type A = ToArray<string | number>

计算过程:

ts
ToArray<string> | ToArray<number>
// string[] | number[]

2️⃣ 分发发生的条件(记住这条)

  • 只有当 T 是“裸类型参数”时才会分发

✅ 分发:

ts
T extends U ? X : Y

❌ 不分发:

ts
[T] extends [U] ? X : Y

3️⃣ 关闭分发(非常重要)

ts
type NoDistribute<T> = [T] extends [string] ? true : false

type A = NoDistribute<string | number>
// false

四、三个用法的对比总结

用法写法发生时机
约束<T extends U>泛型声明
条件T extends U ? X : Y类型计算
分发条件 + 联合自动

五、真实工具类型是怎么用 extends 的?

1️⃣ NonNullable<T>

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

2️⃣ Parameters<T>

ts
type Params<T> = T extends (...args: infer P) => any ? P : never

3️⃣ Awaited<T>

ts
type Awaited<T> = T extends Promise<infer R> ? Awaited<R> : T

六、前端真实场景

1️⃣ 表单值类型判断

ts
type FieldValue<T> =
  T extends HTMLInputElement ? string :
  T extends HTMLSelectElement ? string :
  never

2️⃣ API 状态类型

ts
type ApiResult<T> =
  T extends null ? { success: false } :
  { success: true; data: T }

七、面试必问 3 连击(标准回答)

Q1:extends 在 TS 里有几种用法?

  • 3 种:泛型约束 / 条件类型 / 分发条件类型

Q2:什么时候会发生分发?

  • 当 extends 左边是裸类型参数且为联合类型时

Q3:如何关闭分发?

  • 用元组包一层 [T] extends [U]

八、终极记忆口诀 🧠

  • 声明时限制 → 约束
  • 计算时判断 → 条件
  • 联合会拆 → 分发