Glittering's blog Glittering's blog
Home
  • 学习手册

    • 《JavaScript教程》
    • 《TypeScript教程》
    • 《Git》
    • 《Vite》
    • 《Vue3》
    • 《React18》
    • 《CSS》
    • 《Tailwind CSS》
    • 《ES6 教程》
    • 《TypeScript 从零实现 axios》
  • 技术文档
  • 算法
  • 工作总结
  • 实用技巧
  • collect
About
  • Classification
  • Label
GitHub (opens new window)

Glitz Ma

前端开发工程师
Home
  • 学习手册

    • 《JavaScript教程》
    • 《TypeScript教程》
    • 《Git》
    • 《Vite》
    • 《Vue3》
    • 《React18》
    • 《CSS》
    • 《Tailwind CSS》
    • 《ES6 教程》
    • 《TypeScript 从零实现 axios》
  • 技术文档
  • 算法
  • 工作总结
  • 实用技巧
  • collect
About
  • Classification
  • Label
GitHub (opens new window)
  • 数据类型

  • 实践应用

    • keyof和typeof
    • 映射类型
    • extends的约束、条件、分发
      • 一、用法 1:泛型约束(Constraint)
        • 1️⃣ 最基础示例
        • 2️⃣ 约束 key(超高频)
        • 3️⃣ 约束函数类型
      • 二、用法 2:条件类型(Conditional Types)
        • 1️⃣ 基本语法
        • 2️⃣ 基础示例
        • 3️⃣ 常见内置工具类型
        • Exclude
        • Extract
        • 4️⃣ 判断函数返回值(实战)
      • 三、用法 3:分发条件类型(Distributive)
        • 1️⃣ 看一个例子
        • 2️⃣ 分发发生的条件(记住这条)
        • 3️⃣ 关闭分发(非常重要)
      • 四、三个用法的对比总结
      • 五、真实工具类型是怎么用 extends 的?
        • 1️⃣ NonNullable<T>
        • 2️⃣ Parameters<T>
        • 3️⃣ Awaited<T>
      • 六、前端真实场景
        • 1️⃣ 表单值类型判断
        • 2️⃣ API 状态类型
      • 七、面试必问 3 连击(标准回答)
        • Q1:extends 在 TS 里有几种用法?
        • Q2:什么时候会发生分发?
        • Q3:如何关闭分发?
      • 八、终极记忆口诀 🧠
    • infer关键字(TS的灵魂)
  • 《TypeScript》学习笔记
  • 实践应用
mamingjuan
2020-12-07
目录

extends的约束、条件、分发

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

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

# 1️⃣ 最基础示例

function getLength<T extends { length: number }>(value: T) {
  return value.length
}
1
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

这里:

  • 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

# 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

计算过程:

ToArray<string> | ToArray<number>
// string[] | number[]
1
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

# 四、三个用法的对比总结

用法 写法 发生时机
约束 <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️⃣ API 状态类型

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

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

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

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

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

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

# Q3:如何关闭分发?

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

# 八、终极记忆口诀 🧠

  • 声明时限制 → 约束
  • 计算时判断 → 条件
  • 联合会拆 → 分发
上次更新: 2026/01/07, 09:20:46
映射类型
infer关键字(TS的灵魂)

← 映射类型 infer关键字(TS的灵魂)→

Copyright © 2015-2026 Glitz Ma
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式