在打字稿中的高级条件类型
TypeScript 的高级条件类型通过 T extends U ? X : Y 语法实现类型间的逻辑判断,其核心能力体现在分布式条件类型、infer 类型推断和复杂类型工具的构建。1. 条件类型在裸类型参数上具有分布性,能自动对联合类型拆分处理,如 ToArray
TypeScript 的高级条件类型(Advanced Conditional Types)是类型系统中最强大、最灵活的部分之一。它们允许你根据类型之间的关系动态生成新类型,常用于构建复杂的类型工具、类型守卫和泛型抽象。理解这些特性,能让你写出更安全、更智能的类型代码。

下面是一些关键概念和实用技巧,带你深入掌握高级条件类型。
1. 条件类型的语法与基本原理
条件类型的语法类似于 JavaScript 的三元运算符:

T extends U ? X : Y
意思是:如果类型 T
可以赋值给 U
,那么结果类型是 X
,否则是 Y
。
例子:

type IsString<T> = T extends string ? true : false; type A = IsString<'hello'>; // true type B = IsString<42>; // false
这看起来简单,但它的真正威力体现在与泛型、联合类型和分布式条件类型结合时。
2. 分布式条件类型(Distributive Conditional Types)
当条件类型作用于泛型,并且该泛型出现在 extends
左边时,TypeScript 会自动对联合类型进行“分布”处理。
type ToArray<T> = T extends any ? T[] : never;
如果你传入 string | number
,TypeScript 会将其拆开:
ToArray<string | number> // 等价于: // (string extends any ? string[] : never) | (number extends any ? number[] : never) // 结果是:string[] | number[]
✅ 这种“自动分发”只发生在裸类型参数(naked type parameter)上。如果你把
T
包在元组或对象中,比如[T] extends [any]
,分布性就会关闭。
用途: 常用于将联合类型中的每一项单独处理,比如提取/过滤类型。
3. 类型过滤与提取工具
利用分布式条件类型,我们可以构建强大的类型工具。
提取函数类型
type GetFunction<T> = T extends (...args: any[]) => any ? T : never; type FuncsOnly = GetFunction<string | () => number | number | (s: string) => void>; // 结果:() => number | (s: string) => void
排除某些类型(类似 Exclude
)
type Exclude<T, U> = T extends U ? never : T; type NoString = Exclude<string | number | boolean, string>; // number | boolean
TypeScript 内置的 Exclude<T, U>
就是这么实现的。
提取某些类型(类似 Extract
)
type Extract<T, U> = T extends U ? T : never; type OnlyStringOrNumber = Extract<string | number | boolean, string | number>; // string | number
过滤 null/undefined(类似 NonNullable
)
type NonNullable<T> = T extends null | undefined ? never : T; type A = NonNullable<string | null | undefined>; // string
4. infer
:在条件类型中推断类型
infer
是条件类型中用于“模式匹配”和提取子类型的利器。
提取函数返回值类型(类似 ReturnType
)
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never; type R = ReturnType<() => string>; // string
提取数组元素类型(类似 ElementType
)
type ElementType<T> = T extends (infer U)[] ? U : never; type Item = ElementType<number[]>; // number type Item2 = ElementType<string[]>; // string
提取 Promise 的解析值(类似 Awaited
)
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T; type Value = UnwrapPromise<Promise<string>>; // string type Value2 = UnwrapPromise<number>; // number
infer
可以出现在元组、函数参数、返回值、对象属性等位置,实现复杂的类型解构。
5. 实用高级模式
1. 深度只读(DeepReadonly)
type DeepReadonly<T> = { readonly [K in keyof T]: T[K] extends object ? T[K] extends Function ? T[K] : DeepReadonly<T[K]> : T[K]; };
这里用条件类型判断字段是否是对象,避免对函数递归。
2. 函数重载解析(简化签名)
type FirstParam<F> = F extends (arg: infer P) => any ? P : never; type ID = FirstParam<(id: string) => void>; // string
3. 联合转交叉类型(高级技巧)
有时你想把 string | number
转成 string & number
(虽然结果是 never
),但更常见的是用于函数参数的“逆变”处理。
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never; type T = UnionToIntersection<{a:1} | {b:2}>; // {a:1} & {b:2}
这个技巧常用于类型推导中“合并”多个类型。
6. 常见陷阱与注意事项
never 在联合类型中会被忽略
type T = string | never; // 等价于 string
所以
Exclude
中用never
来“过滤掉”类型是有效的。条件类型是惰性的
条件类型只有在被实例化时才会计算。例如:
type Foo<T> = T extends string ? string : number; type A = Foo<any>; // type is string | number
因为
any
与string
的关系是“模糊的”,TypeScript 会保守地返回string | number
。never 的特殊行为
never
是所有类型的子类型,所以在条件类型中:type T = never extends string ? true : false; // true
但这不意味着
never
是字符串,而是类型系统规则如此。
总结
高级条件类型是 TypeScript 类型编程的核心。结合
extends
、infer
和分布式行为,你可以:- 过滤、提取、转换类型
- 实现类型级“逻辑判断”
- 构建复杂的泛型工具(如
Pick
、Omit
、ReturnType
等)
虽然一开始看起来像魔法,但只要理解了“类型是集合”、“条件类型是集合判断”这一思想,就能逐步掌握。
基本上就这些。多写、多试,你会发现类型系统比想象中更强大。
以上是在打字稿中的高级条件类型的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undress AI Tool
免费脱衣服图片

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

AdeadlockinJavaoccurswhentwoormorethreadsareblockedforever,eachwaitingforaresourceheldbytheother,typicallyduetocircularwaitcausedbyinconsistentlockordering;thiscanbepreventedbybreakingoneofthefournecessaryconditions—mutualexclusion,holdandwait,nopree
![您目前尚未使用附上的显示器[固定]](https://img.php.cn/upload/article/001/431/639/175553352135306.jpg?x-oss-process=image/resize,m_fill,h_207,w_330)
Ifyousee"YouarenotusingadisplayattachedtoanNVIDIAGPU,"ensureyourmonitorisconnectedtotheNVIDIAGPUport,configuredisplaysettingsinNVIDIAControlPanel,updatedriversusingDDUandcleaninstall,andsettheprimaryGPUtodiscreteinBIOS/UEFI.Restartaftereach

Micronautisidealforbuildingcloud-nativeJavaapplicationsduetoitslowmemoryfootprint,faststartuptimes,andcompile-timedependencyinjection,makingitsuperiortotraditionalframeworkslikeSpringBootformicroservices,containers,andserverlessenvironments.1.Microna

理解JCA核心组件如MessageDigest、Cipher、KeyGenerator、SecureRandom、Signature、KeyStore等,它们通过提供者机制实现算法;2.使用SHA-256/SHA-512、AES(256位密钥,GCM模式)、RSA(2048位以上)和SecureRandom等强算法与参数;3.避免硬编码密钥,使用KeyStore管理密钥,并通过PBKDF2等安全派生密码生成密钥;4.禁用ECB模式,采用GCM等认证加密模式,每次加密使用唯一随机IV,并及时清除敏

SpringDataJPA与Hibernate协同工作的核心是:1.JPA为规范,Hibernate为实现,SpringDataJPA封装简化DAO开发;2.实体类通过@Entity、@Id、@Column等注解映射数据库结构;3.Repository接口继承JpaRepository可自动实现CRUD及命名查询方法;4.复杂查询使用@Query注解支持JPQL或原生SQL;5.SpringBoot中通过添加starter依赖并配置数据源、JPA属性完成集成;6.事务由@Transactiona

runtheapplicationorcommandasadministratorByright-clickingandSelecting“ runasAdministrator” toensureeleeleeleeleviledprivilegesareAreDranted.2.checkuseracccountcontontrol(uac)uac)

Pattern类用于编译正则表达式,Matcher类用于在字符串上执行匹配操作,二者结合可实现文本搜索、匹配和替换;首先通过Pattern.compile()创建模式对象,再调用其matcher()方法生成Matcher实例,接着使用matches()判断全字符串匹配、find()查找子序列、replaceAll()或replaceFirst()进行替换,若正则包含捕获组,可通过group(n)获取第n组内容,实际应用中应避免重复编译模式、注意特殊字符转义并根据需要使用匹配模式标志,最终实现高效
