extends的约束、条件、分发
# 一、用法 1:泛型约束(Constraint)
- 限制泛型的“取值范围”
# 1️⃣ 最基础示例
function getLength<T extends { length: number }>(value: T) {
return value.length
}
1
2
3
2
3
- ✅ string / array
- ❌ number
📌 extends = T 必须满足某个结构
# 2️⃣ 约束 key(超高频)
function getValue<T, K extends keyof T>(obj: T, key: K) {
return obj[key]
}
1
2
3
2
3
这里:
K只能是T的 key- 否则直接报错
# 3️⃣ 约束函数类型
type Fn<T extends (...args: any[]) => any> = T
1
React / Vue hooks 类型常见写法。
# 二、用法 2:条件类型(Conditional Types)
- 像三元表达式一样返回不同类型
# 1️⃣ 基本语法
T extends U ? X : Y
1
# 2️⃣ 基础示例
type IsString<T> = T extends string ? true : false
type A = IsString<'a'> // true
type B = IsString<123> // false
1
2
3
4
2
3
4
# 3️⃣ 常见内置工具类型
# Exclude
type MyExclude<T, U> = T extends U ? never : T
1
# Extract
type MyExtract<T, U> = T extends U ? T : never
1
# 4️⃣ 判断函数返回值(实战)
type Return<T> = T extends (...args: any[]) => infer R ? R : never
1
(这就是 ReturnType 的原理)
# 三、用法 3:分发条件类型(Distributive)
- 条件类型 + 联合类型 = 自动拆分计算
📌 这是最容易懵的一部分
# 1️⃣ 看一个例子
type ToArray<T> = T extends any ? T[] : never
type A = ToArray<string | number>
1
2
3
2
3
计算过程:
ToArray<string> | ToArray<number>
// string[] | number[]
1
2
2
# 2️⃣ 分发发生的条件(记住这条)
- 只有当
T是“裸类型参数”时才会分发
✅ 分发:
T extends U ? X : Y
1
❌ 不分发:
[T] extends [U] ? X : Y
1
# 3️⃣ 关闭分发(非常重要)
type NoDistribute<T> = [T] extends [string] ? true : false
type A = NoDistribute<string | number>
// false
1
2
3
4
2
3
4
# 四、三个用法的对比总结
| 用法 | 写法 | 发生时机 |
|---|---|---|
| 约束 | <T extends U> | 泛型声明 |
| 条件 | T extends U ? X : Y | 类型计算 |
| 分发 | 条件 + 联合 | 自动 |
# 五、真实工具类型是怎么用 extends 的?
# 1️⃣ NonNullable<T>
type NonNullable<T> = T extends null | undefined ? never : T
1
# 2️⃣ Parameters<T>
type Params<T> = T extends (...args: infer P) => any ? P : never
1
# 3️⃣ Awaited<T>
type Awaited<T> = T extends Promise<infer R> ? Awaited<R> : T
1
# 六、前端真实场景
# 1️⃣ 表单值类型判断
type FieldValue<T> =
T extends HTMLInputElement ? string :
T extends HTMLSelectElement ? string :
never
1
2
3
4
2
3
4
# 2️⃣ API 状态类型
type ApiResult<T> =
T extends null ? { success: false } :
{ success: true; data: T }
1
2
3
2
3
# 七、面试必问 3 连击(标准回答)
# Q1:extends 在 TS 里有几种用法?
- 3 种:泛型约束 / 条件类型 / 分发条件类型
# Q2:什么时候会发生分发?
- 当 extends 左边是裸类型参数且为联合类型时
# Q3:如何关闭分发?
- 用元组包一层
[T] extends [U]
# 八、终极记忆口诀 🧠
- 声明时限制 → 约束
- 计算时判断 → 条件
- 联合会拆 → 分发
上次更新: 2026/01/07, 09:20:46