Typescript中extends做条件类型时的几种行为

Extends用于条件类型判断时,有如下行为:

1,简单情况

typescript 复制代码
type A = ('X' | 'Y') extends 'X' ? '1' : '2'

作用:判断 前一个类型 能不能赋值给后一个类型

白话:

typescript 复制代码
const a: 'X' | 'Y' = p1
const b: 'X' = p2

所有能填到这个p1的位置的东西,是不是都能填到p2的位置上

2,含有泛型的情况

typescript 复制代码
type Diff<T> = T extends 'X' ? '1' : '2'

type A = Diff<'X' | 'Y'>

对于属于"裸类型参数"(即T)的检查类型,条件类型会在实例化时期自动分发到联合类型上

原文 : Conditional types in which the checked type is a naked type parameterare called distributive conditional types. Distributive conditional types are automatically distributed over union types during instantiation

白话:没有被额外包装的 泛型参数,拿来做条件类型判断时,会将该 泛型 的联合类型拆开,分别进行判断。

过程:

typescript 复制代码
'X' extends 'X' // => '1'
'Y' extends 'X' // => '2'
// 最终拿到联合类型 '1' | '2'

思考:Exclude是如何实现的?

Exclude源码:

typescript 复制代码
/**
 * Exclude from T those types that are assignable to U
 */
type Exclude<T, U> = T extends U ? never : T;

解析: T是一个泛型,它符合"裸类型参数",此时使用extends做条件判断时,传入T的联合类型会被拆开对比。

例如:

typescript 复制代码
type B = Exclude<'X'|'Y', 'X'> // type B = "Y"

实际对比的过程为:

typescript 复制代码
type Exclude<T, U> = T extends U ? never : T;
'X' extends 'X' // => never
'Y' extends 'X' // => 'Y'
// 最终得到 never | 'Y' , 也就是 'Y'

这就是Exclude的原理。

3,含有泛型,但不是"裸类型参数"

简单处理:使用元组包裹,使泛型不是一个裸类型参数

typescript 复制代码
type Diff<T> = [T] extends ['X'] ? '1' : '2'
type A = Diff<'X' | 'Y'>
// 此时不会被分发,结果:2

以下两种特殊情况不需要记忆,用到的时候查一下就好:

特殊情况 any:

当用any做检查类型,不管是否传入泛型

1:在判断条件非any的情况,都会返回判断结果的联合类型

typescript 复制代码
type Tmp1 = any extends string ? 1 : 2;  // 1 | 2
typescript 复制代码
type Tmp2<T> = T extends string ? 1 : 2;

type Tmp2Res = Tmp2<any>; // 1 | 2

2:判断条件为any的情况,仍然会进行判断

typescript 复制代码
type Special1 = any extends any ? 1 : 2; // 1
typescript 复制代码
type Special2<T> = T extends any ? 1 : 2;

type Special2Res = Special2<any>; // 1

特殊情况never

1:直接使用,仍然会进行判断

typescript 复制代码
type Tmp3 = never extends string ? 1 : 2; // 1

2:通过泛型参数传入,会跳过判断,直接返回never

typescript 复制代码
type Tmp4<T> = T extends string ? 1 : 2;

type Tmp4Res = Tmp4<never>; // never

3:判断条件为never的情况,仍然进行判断

typescript 复制代码
type Special3 = never extends never ? 1 : 2; // 1

但即使判断条件为never,如果传入泛型,也会跳过判断,直接返回never

typescript 复制代码
type Special4<T> = T extends never ? 1 : 2;

type Special4Res = Special4<never>; // never
相关推荐
Setsuna_F_Seiei8 小时前
前端转型 Agent 开发 06 之 Agent Memory 记忆系统(让 Agent 更智能,更懂你)
前端·agent·ai编程
zhangzeyuaaa8 小时前
Ruby 多线程、GVL(GIL)与 Mutex 完全指南
开发语言·前端·ruby
默_笙9 小时前
🌊 向量库和 ES 都查不出"关系",我只好给奶茶建了一张人脉网
前端·javascript
优选资讯9 小时前
标签打印软件怎么对接 Excel 数据
前端·excel
一个风轻云淡10 小时前
GCC 和 GDB命令简单解读
java·linux·前端
u01110267511 小时前
图片处理接口如何统一错误信息 前端提示与后端错误码设计
前端·状态模式
福兮说11 小时前
浏览器里把 iPhone 的 HEIC 转成 JPG:Chrome 解不开、转完大了七成、拍摄时间全丢,六个坑实测
前端·javascript·图像处理·chrome·ios·iphone·heic
libokaifa11 小时前
把语音模型塞进手机:sherpa-onnx 在 Android 上的 ASR / TTS
前端
deli00712 小时前
DLA 枝晶生长实测:5000 个粒子集体停摆之后,分形维数收敛到 1.70
前端
IT_陈寒12 小时前
Redis卡顿的锅,这次真不是大key的错
前端·人工智能·后端