「这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战」
前言
我们在学习 Typescript 高级知识之前,先提前温习下前面的知识: Typescript预备知识、Typescript基础知识 和 Typescript进阶。
高级知识
类型操作
我们前面在 Typescript
进阶知识学习了,简单的类型操作——keyof
,那么下面我们继续学习 3 种相对复杂的类型操作。
映射类型
在了解映射类型之前,我们不妨看一个例子。
我们有一个User接口,现在有一个需求是把User接口中的成员全部变成可选的,我们应该怎么做?难道要重新一个个:
前面加上?
,手都加酸啦,有没有更便捷的方法呢?
interface User {
username: string
id: number
token: string
avatar: string
role: string
}
复制代码
这个时候映射类型就派上用场了,映射类型的语法是[K in Keys]
:
- K:类型变量,依次绑定到每个属性上,对应每个属性名的类型。
- Keys:字符串字面量构成的联合类型,表示一组属性名(的类型)。
我们使用映射类型,来实现上述需求,具体代码如下:
interface User {
username: string
id: number
token: string
avatar: string
role: string
}
type partial<T> = { [K in keyof T]?: T[K] };
type partialUser = partial<User>;
复制代码
映射类型,其实是一种创建对象类型的方法。
映射类型 VS 对象类型
我们可以用描述集合的方法来形象地理解对象类型和映射类型:
描述集合的方法 | 描述对象类型的方法 | 举例 |
---|---|---|
列举法 | 对象类型 | type Person = {name: string, age: number} |
公式法 | 映射类型 | type Mapped = { [K in UnionType]: ValueType |
映射类型、keyof、typeof、可选修饰符、只读修饰符结合
import { Equal } from '@type-challenges/unils';
type User = {
id: number;
name: string;
age: number;
};
// 所有字段变为可选
type OptionalUser = { [K in keyof User]?: User[K] }
// 所有字段变为 nullable 的
type NullableUser = { [K in keyof User]: User[K] | null }
// 所有字段变为只读的
type ReadonlyUser = { readonly [K in keyof User]: User[K] }
// 所有字段去除只读
type User2 = { -readonly [K in keyof ReadonlyUser]: User[K] }
type R1 = Equal<User2, User>;// true
// 所有字段去除可选
type User3 = { [K in keyof OptionalUser]-?: User[K] }
type R2 = Equal<User3, User>;// true
复制代码
模板字面量类型
模板字面量类型,是在TS4.1引入的。通过它我们可以更方便地创建字符串字面量类型。
模板字面量 vs 模板字符串
模板字面量语法与模板字符串相同。我们下面来具体对比看看吧。
条件类型
条件类型,是在TS2.8时引入的。简单理解,条件类型就是通过判断两个类型之间的关系, 根据判断结果返回不同类型。其语法和三目运算符(X ? A : B)一样。
条件类型 vs 三目运算符
其他语言类似条件类型
其他语言中也有类似条件类型的特性。比如C++中可以通过模板特化实现。
#include <iostream>
template<typename T> // primary template
struct is_void : std::false_type{};
// 默认对任意T都继承自false_type
template<> // explicit specialization for T = void
struct is_void<void> : std::true_type{};
// 但当T=void时继承true_type
int main()
{
std::cout << is_void<char>::value << '\n';// false_type::value = 0
std::cout << is_void<void>::value << '\n';// true_type::value = 1
}
复制代码
条件类型高级话题
条件类型还有很多相关的知识话题,有兴趣可自行研究学习:
- 条件类型中的分配(Distributive Conditional Types) 2. infer关键字
- UnionToIntersection<U>
- 型变Variance
常用工具类
上图是 Typescript 常用的工具类型,详情可见lib.es5.d.ts。
总结
学习完Typescript知识,我们可以认为TS的类型系统本身是一个用来“操作、创建”类型的“语言”。
- 列举 ↔ 顺序执行
- 映射类型 ↔ 循环
- 条件类型 ↔ 条件判断
划重点:我们通过TS类型系统提供的这个 “语言”,精确的描述我们需要的类型。TS回报给我们的就是编译期就将问题提前暴露出来。代码更健壮、更易扩展。
Typescript 资源
书名 | 图片 | 特点 |
---|---|---|
《TypeScript编程》 | 全面 | |
《深入理解TypeScript》 | 深入 | |
《高效TypeScript》 | 指导性、原则性 | |
《TypeScript类型编程》 | 着重TS类型系统 |