探索TypeScript辅助工具类型的应用场景与最佳实践
前言
👉 TypeScript
中的辅助工具类,主要是用于帮助开发者创建可维护性高的代码自动检测机制,举个例子说明以下: 在项目过程中,我们一般需要将环境定义到环境变量中,然后整体项目的编译、打包运行,都依赖于该环境变量
,TypeScript
中的辅助工具类就是用来基于该环境变量来创建对应的类型,从基准类型中创建新的类型!!
🌠 这边整理了关于TypeScript
中所提供的辅助工具类型清单,并根据实际的应用场景进行的划分, 👇 下面将进行一一的分析与场景应用举例!
属性修饰符转换
Required<Type>
Required
用于将类型
Type
中的所有可选属性变为必选属性,一般接受一个有可选属性的类型,然后返回一新的类型,这个新的类型中的所有属性都是必须属性,比如有 👇 的一个例子:
1 | type MyType = { |
🌟 从上述的运行结果,我们可以看出RequireMyType已经是所有属性都必须传递的了!
Readonly
用于将
Type
中的所有可写属性变为只读属性
1 | type MyType = { foo: string; bar: number; }; |
🌟 这里对obj的foo属性进行赋值,将会提示foo不能被赋值的异常信息
😕 与Object.frozen()
、as const
的区别:
使用 | 作用 | 使用场景 | 影响范围 |
---|---|---|---|
Object.frozen() |
冻结一个对象,使其属性属性不可变,一般用于运行时 | 用于防治对象被意外修改,以保护对象的数据完整性 | 作用于运行时整个对象,包括对象的属性值 |
Readonly<Type> |
将类型Type 中的所有属性设置为只读,防止对属性值的修改,在编写代码期间提示 |
适用于TypeScript 中需要确保对象属性不被修改的情况下,提高代码的安全性和可维护性 |
只影响类型系统,不会影响运行时,就算是在编码中修改了,依然可以修改 |
as const |
将表达式的类型受灾为其字面量类型,即不可变的常量类型 | 适用于TypeScript 中需要去报变量的值不被修改的情况,通常用于声明变量或者确保数组和对象的不可变性 |
通常用于受灾特定表达式的类型,以确保表达式的值不被修改 |
:+1: 关于as const
,这边再补充多一个例子
1 | const arr = [1, 2, 3] as const; // 这里的arr数组将会收窄为联合类型1 | 2 | 3 |
类型与、或、非、子集
这边针对其应用场景,将
Partial<Type>
、Omit<Type, key>
、Extract<Type, Uniton>
、Exclude<UnionType, ExcludeMembers>
几个辅助工具类进行归类
Partial
用于将Type类型中的所有属性都设置为可选属性,一般是接收一个
Type
作为参数,然后返回一个新的类型,新的类型中的所有属性都是可选的,可以存在也可以不存在,比如有 👇 的一个例子:
1 | type MyType = { foo: string, bar: number } |
Pick<Type, Keys>
用于从类型
Type
中选择指定的属性Keys
来构造一个新的类型,具体来说,Pick<Type, Keys>
接收两个类型参数:
Type
: 代表待挑选的类型;Keys
: 代表要选择的属性键的集合,可以是单个属性,也可以是属性名称的联合类型
然后,Pick
将从Type
类型中选择出指定的属性,构造出一个新的类型,该类型包含了Keys
中声明的属性。
比如有 👇 的一个例子:
1 | type MyType = { |
Omit<Type, Keys>
用于从类型
Type
中剔除Keys
指定的属性,然后构造成为一个新的类型,一般来说,Omit<Type, Keys>
接收两个类型参数:
Type
: 代表源类型;Keys
: 代表要排除的属性键的集合,可以是单个类型,也可以是属性名称的联合类型
然后,Omit
将从Type
类型中剔除Keys
所声明的属性
比如有 👇 的一个例子:
1 | type MyType = { |
:+1: Omit<Type, Keys>
与Pick<Type, Keys>
在功能上是相反的!!
Extract<UnionType, Union>
用于从联合类型
UnionType
中提取出与类型Union
兼容的成员,并返回一个新的类型,一般来说,Extract
接收两个类型参数:
UnionType
: 表示要提取的成员的类型;Union
: 表示从UnionType
中提取的成员的联合类型;
然后,Extract
将从UnionType
中提取出所有类型与Type
兼容的成员,并返回一个新的类型,该类型只包含了UnionType
中与Union
兼容的成员。
比如有 👇 的一个例子:
1 | type MyType = 'a' | 'b' | 'c' | 'd' |
Exclude<UnionType, ExcludedMembers>
用于从联合类型
UnionType
中排除指定的成员ExcludeMembers
,并返回一个新的类型,一般来说,Exclude<UnionType, ExcludedMembers>
接收两个类型的参数:
UnionType
: 表示源联合类型;ExcludedMembers
: 表示要排除的成员类型
然后,Exclude
将从UnionType
中排除掉所有类型为ExcludedMembers
的类型,并返回一个新的类型!
比如有 👇 的一个例子:
1 | type MyUnion = 'a' | 'b' | 'c' | 'd' |
:+1: Exclude<UnionType, ExcludedMembers>
与Extract<UnionType, Union>
在功能上是相反的!!
工具辅助
NonNullable
用于移除类型
Type
中的null
以及undefined
类型,从而得到一个新的类型,一般来说,NonNullable
接收一个类型参数Type
,然后返回一个新的类型,这个新的类型中移除了Type
中的null
以及undefined
类型
比如有 👇 的一个例子:
1 | type MyType = string | null | undefined |
Awaited
用途:用于获取一个Promise的返回类型,
Awaited<Type>
接受一个范型参数Type
,这个Type
是一个Promise类型
,然后返回该Promise的resolved
类型,也就是Promise解析后的值类型。
👉 一般用来帮助编写异步代码,并获取Promise的resolved值的类型,比如在使用async/await
的时候,可以通过Awaited<Type>
来获取一个异步函数的返回值的类型,如 👇 代码所示:
1 | async function fetchData(): Promise<{ id: number, name: string }> { |
⚠ 这里的Promise
是TypeScript
中的内置类型,但它并不是一个范型辅助类型,它代表了一个异步操作的结果,一般用于处理异步任务,虽然这个Promise
并不是一个范型辅助类型,但是它是一个范型类型,因为它可以接受一个类型参数来指定异步操作的结果类型,👉 在使用Promise
的时候,可以通过范型参数来指定异步操作成功时所产生的值的类型,从而提高代码的类型安全性!
Record<Keys, Type>
用于创建一个新的类型,该类型由
key-value
组成的对象,一般来说,Record<Keys, Type>
接收两个类型参数:
Keys
: 代表对象的键的类型;Type
: 代表对象的值的类型。
👉 这有点像java中的Map<String, T>
对象,只不过这里的Keys
可以是string
、symbol
⚠ 这里的Record<Keys, Type>
只是一个类型创建器,它并不会创建对象实例,而是用来定义对象类型,比如有 👇 的一个例子:
1 | type MyRecord = Record<string, number> |
🤩 上述中的MyRecord
代表了该类型必须是一个key=string,value=number类型的对象,而且就相当于是类型索引定义
, 😕 这个类型索引定义又是个什么?
索引签名
在实际的项目coding过程中,有时我们并不能事先知晓所有的属性,但是我们清楚对象所有值的类型,那么我们可以定义以下的这种的对象类型:
1 | interface StringArray { |
🌟 这里我们定义了一个字符串类型的数组以及一个字符串Map对象,可以辅助我们在编码的过程中一看到这个类型就知道这个类型的成员结构!
函数相关
主要用于声明函数中的相关成员属性的类型
Parameters
用于获取函数类型
Type
的参数类型所组成的元祖类型,该元祖类型包含了Type
函数的所有的参数类型
1 | type MyFunction = (x: number, y: string) => void; |
ConstructorParameters
用于获取构造函数类型
的参数类型所组成的元祖类型,该元祖类型包含了构造函数 T
的所有参数类型
1 | class MyClass {} |
ReturnType
用于获取函数类型
Type
的返回值类型,一般是接受一个函数类型Type
作为参数,然后返回该函数类型的返回值类型,也就是函数Type的执行结果所对应的类型,比如有 👇 的一个例子
1 | type MyFunction = () => number; |
🌠 这里MyReturnType
的类型将会是一个number
,ReturnType<Type>
对于获取函数类型的返回值类型非常方便,特别是在使用高阶函数或者范型函数是,利用它可以帮助我们推断函数的返回值类型,从而提高代码的可读性和可维护性。
InstanceType
用于获取构造函数类型
Type
的实例类型,一般来说,InstanceType<Type>
接收一个构造函数类型Type
作为参数,然后返回该构造函数类型的实例类型。
比如,有 👇 的一个例子:
1 | class MyClass{ |
ThisParameterType
用于获取函数类型
Type
中的this
的参数类型,也就是这个函数的调用方的上下文类型,比如有 👇 的一个类型:
1 | type MyFunction = (this: MyClass, x: number, y: number) => void; |
OmitThisParameter
用于从函数类型
Type
中移除this
参数,并返回一个新的函数类型
1 | class MyClass {} |
ThisType
用于指定函数中的
this
上下文类型。
字符串处理
这边主要是针对常量字符串类型的限定,以提供字符串的静态保证,帮助减少代码中的错误!
Uppercase
用于将字符串类型
StringType
中的所有字符转换为大写形式,一般接收一个字符串类型作为参数,返回返回一个新的字符串类型,该类型中的所有字符都被转换为大写形式。
一般可用作字符串的静态保证,帮助减少代码中的错误!
Lowercase
用于将字符串类型
StringType
中的所有字符转换为小写形式,一般接收一个字符串类型作为参数,返回返回一个新的字符串类型,该类型中的所有字符都被转换为小写形式。
Capitalize
用于将字符串类型
StringType
中的第一个字符转换为大写形式,一般接收一个字符串类型作为参数,返回返回一个新的字符串类型,该类型中的第一个字符都被转换为大写形式。
Uncapitalize
用于将字符串类型
StringType
中的第一个字符转换为小写形式,一般接收一个字符串类型作为参数,返回返回一个新的字符串类型,该类型中的第一个字符都被转换为小写形式。
总结
TypeScript
中的辅助工具类虽然不能直接深入到代码逻辑中,但是就像TypeScript
一样,它可以帮助我们在编写代码的时候,进行自动的类型检测,提前预知到可能会发生的异常问题,比如空数据的情况,提示代码编写者进行非空判断,比如某些字段必须传递,或者不可修改等等,而上述的这些辅助工具类,可以用于进行类型转换、操作和组合,以简化代码并提高代码的可读性和维护性!!