当前位置:网站首页>TS进阶之条件类型
TS进阶之条件类型
2022-06-13 11:16:00 【JonnyLan】
前端开发者对Javascript中的三元表达式应该都很熟悉,利用三元表达式可以很方便实现根据输入值得到不同的输出结果。 TypeScript对类型也提供了类似的语法,和Javascript唯一的区别就是TypeScript操作的是数据类型。
基本语法
基本使用
T extends U ? X : Y;
T
U
X
Y
四个是占位符,分别表示四种类型;T extends U
表示T
类型能被赋值给U
类型,这里还涉及到TS类型兼容性。
几个简单的例子
- 判断类型是否是
string
类型
type IsString<T> = T extends string ? true : false;
type C11 = IsString<string>; // true
type C22 = IsString<number>; // false
type C1 = IsString<"1">; // true
type C2 = IsString<1>; // false
重点:例子中的
true
和false
是类型(字面量类型),不是值。
- 如果是
Animal
类型得到number
类型,否则为string
类型
interface Animal {
live(): void;
}
interface Dog extends Animal {
woof(): void;
}
type IsAnimal<T> = T extends Animal ? number : string;
type C3 = IsAnimal<Dog> // number
type C4 = IsAnimal<RegExp> // string
TS进阶之keyof中的例子
- 实现
Omit
type MyOmit<T, K> = { [P in keyof T as P extends K ? never : P]: T[P] };
- 给对象类型添加属性
type AppendToObject<T, U extends keyof any, V> = {[P in keyof T | U]: P extends keyof T ? T[P] : V}
条件类型可复合使用
例子如下:获取类型的名称
type TypeName<T> = T extends string
? 'string'
: T extends number
? 'number'
: T extends boolean
? 'boolean'
: T extends undefined
? 'undefined'
: T extends Function
? 'function'
: 'object';
这个使用方法应该也比较好理解,不过多解释了。
条件类型的分发特性
如果对条件类型的分发特性不太熟悉的同学可能会对Exclude
,Extract
等工具类型的实现有疑问,接下来我就使用Exclude
来具体介绍下条件类型的分发特性。
重点:条件的分发特性主要针对的
T
是联合类型
Exclude的具体执行逻辑
type Exclude<T, U> = T extends U ? never : T;
type C5 = Exclude<'a' | 'b' | 'c', 'a' | 'b'> // 'c'
解释:
- 对联合类型
T
进行分发变成:'a' extends 'a'| 'b' ? never : 'a' | 'b' extends 'a'| 'b' ? never : 'b' | 'c' extends 'a'| 'b' ? never : 'c'
- 分别计算的结果是
never | never | 'c'
- 最后的结果:
c
条件类型的分发必须是裸类型
裸类型是指没有被数组,元组和Promise等包装过的类型。
对比例子如下:
type IsString2<T> = [T] extends string[] ? "IS a String" : "Not a String";
type C7 = IsString2<string | number>;
// 结果: "Not a String"
type IsString3<T> = T extends string ? "IS a String" : "Not a String";
type C8 = IsString3<string | number>;
// 结果: "IS a String" | "Not a String"
IsString2
中的[T]
被数组包装过了,不会进行分发,直接判断[string | number] extends string[]
, 得到了"Not a String"
;IsString3
中的[T]
没被包装过,会进行分发,得到"IS a String" | "Not a String"
;
never是空的联合类型
如果判断一个类型是否是never
,可能最开始想到的是:
type IsNever<T> = T extends never ? true : false; //
这个是错误的,因为 never代表的是空的联合类型,相当于没有,所有不会执行,最后也是never
类型,不会得到true
。
正确的解决逻辑是将never变成元组类型就可以了。
type IsNever<T> = [T] extends [never] ? true : false; //
一些案例
获取数组类型的第一个元素的类型
type First<T extends any[]> = T extends never[] ? never : T[0];
type arr1 = ['a', 'b', 'c']
type C6 = First<arr1> // 'a'
注意 这里的
'a'
,'b'
,'c'
,是类型,是类型,是类型;
Pick 具有某个类型的属性
type PickByType<T, U> = { [P in keyof T as T[P] extends U ? P : never]: T[P] };
type OnlyBoolean = PickByType<{
name: string
count: number
isReadonly: boolean
isEnable: boolean
}, boolean>
// 结果:
{
isReadonly: boolean;
isEnable: boolean;
}
判断Any
export type IsAny<T> = 0 extends (1 & T) ? true : false
type IsAny<T> = 0 extends (1 & T) ? true : false
type C9 = IsAny<any>; // true
type C10 = IsAny<string>; // false
解释:
any & 1 = any
,0 extends any
成立,所以返回true
; 具体解释地址
判断两个类型完全相等
export type Equal<X, Y> =
(<T>() => T extends X ? 1 : 2) extends
(<T>() => T extends Y ? 1 : 2) ? true : false
解释:通过构造一个函数类型来对比两个函数类型是否完全相等。具体解释地址
infer
条件类型语法中可以使用infer
进行类型推断,下篇主要介绍这部分内容。
先来个官方的获取参数类型的例子:
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
边栏推荐
- F2. nearest beautiful number (hard version)
- 17张图:读懂国内首个《主机安全能力建设指南》
- Gauss elimination for solving N-element equations
- 求组合数四种方法
- 面试技巧问答
- We spent a weekend migrating 3.7 million lines of code to typescript
- To vent their dissatisfaction with their superiors, Baidu post-95 programmers were sentenced to 9 months for deleting the database
- Pagoda access changed from IP to domain name
- 【TcaplusDB知识库】TcaplusDB常规单据介绍
- Finally, the monthly income is 20000!!
猜你喜欢
Database learning notes (Chapter 15)
区间修改乘和加(理解懒标记的好例题)
【TcaplusDB知识库】Tmonitor系统升级介绍
欧拉函数和线性筛求欧拉函数
Go needs to add an arrow syntax, which is more like PHP!
关于 SAP Spartacus CmsService.getComponentData 可能的优化思路
Chapter VII document management
【TcaplusDB知识库】Tmonitor单机安装指引介绍(二)
基于Vue+Nest.js+MySQL的跨平台开源社区运营管理系统
Go 要加个箭头语法,这下更像 PHP 了!
随机推荐
[ROS] moveit rviz seven DOF Manipulator Simulation
欧拉函数和线性筛求欧拉函数
宝塔中navicat连接mysql
Analysis and summary of 2021ccpc online games
ue5 小知识点 random point in Bounding Boxf From Stream
恶意代码实战分析Lab05-01
日志1111
【TcaplusDB知识库】TcaplusDB Tmonitor模块架构介绍
Folder data synchronization tool sync folders Pro
Pagoda access changed from IP to domain name
容斥原理(能被整除的数)
Alibaba's employees decreased by 4000 in the first quarter; Programmers wrote scripts to hang up vaccine numbers and were arrested for making a profit of 400000 yuan; Sohu encounters epic email fraud,
宝塔访问从IP改为域名
[tcapulusdb knowledge base] Introduction to tmonitor background one click installation (I)
5.5 clock screensaver
Gauss elimination for solving N-element equations
[tcapulusdb knowledge base] tcapulusdb cluster management introduction
Interval modification multiplication and addition (a good example of understanding lazy tags)
[tcapulusdb knowledge base] tcapulusdb Model Management Introduction
Determine the maximum match between bipartite graph and bipartite graph