工具类
作者:Choi Yang
更新于:17 小时前
字数统计:976 字
阅读时长:4 分钟
expectType
typescript
npm install --save-dev tsdtypescript
import { expectType } from 'tsd'
expectType<string>('Chocolate') // √
expectType<string>(1999) // ×工具类型
typescript
// 工具类型
type MaybeNull<T> = T | null
function process13(input: MaybeNull<{ handler: () => {} }>) {
input?.handler()
}
type MaybeArray<T> = T | T[]
function ensureArray13<T>(input: MaybeArray<T>): T[] {
return Array.isArray(input) ? input : [input]
}映射类型
typescript
// 映射类型
type Stringify<T> = {
[K in keyof T]: string;
}
interface Foo {
prop1: string
prop2: number
prop3: boolean
prop4: () => void
}
type StringifiedFoo = Stringify<Foo>
// 等价于
interface StringifiedFooAns {
prop1: string
prop2: string
prop3: string
prop4: string
}
// 等价于
interface StringifiedFooAns2 {
prop1: string
prop2: string
prop3: string
prop4: string
}高级操作:克隆类型
typescript
type Clone<T> = {
[K in keyof T]: T[K];
}IsAny 与 IsUnknown
typescript
// IsAny 与 IsUnknown
type IsAny<T> = 0 extends 1 & T ? true : false
type IsUnknown<T> = unknown extends T
? IsAny<T> extends true
? false
: true
: false属性修饰工具类型
typescript
// 属性修饰工具类型
type Partial<T> = {
[P in keyof T]?: T[P]; // 标记属性可选
}
type Partial_2<T> = {
[P in keyof T]+?: T[P]; // 和上述相等,更好理解,表示在原本的属性上添加可选
}
type Required<T> = {
[P in keyof T]-?: T[P]; // -? 表示原本属性上如果有 ? 这个标记,则移除它
}
type Readonly<T> = {
readonly [P in keyof T]: T[P];
}结构工具类型
Record
typescript
// 内置类型 Record
type Record<K extends keyof any, T> = {
[P in K]: T;
}
// 键名均为字符串,键值类型未知
type Record_1 = Record<string, unknown>
// 键名均为字符串,键值类型任意
type Record_2 = Record<string, any>
// 其中,Record<string, unknown> 和 Record<string, any> 是日常使用较多的形式,通常我们使用这两者来代替 object 。
// 键名为字符串或数字,键值类型任意
type Record_3 = Record<string | number, any>typescript
// 例子:用于字典
interface Dictionary<T> {
[index: string]: T
}
interface NumericDictionary<T> {
[index: number]: T
}Pick
typescript
// 结构处理工具类型 Pick
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
}
// 例子:
interface Foo {
name: string
age: number
isVip: boolean
}
type PickedFoo = Pick<Foo, 'name' | 'age'>Omit
typescript
// Omit 是基于 Pick 实现的,反向工具类型基于正向工具类型实现
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>Exclude<A, B> 的结果就是联合类型 A 中不存在于 B 中的部分,举例:
typescript
type Tmp1 = Exclude<1, 2> // 1
type Tmp2 = Exclude<1 | 2, 2> // 1
type Tmp3 = Exclude<1 | 2 | 3, 2 | 3> // 1
type Tmp4 = Exclude<1 | 2 | 3, 2 | 4> // 1 | 3那么 Exclude<keyof T, K> 其实就是 T 的键名联合类型中剔除了 K 的部分
集合工具类型
typescript
// 交集
type Extract<T, U> = T extends U ? T : never
// 差集
type Exclude<T, U> = T extends U ? never : Ttypescript
// 集合工具类型汇总
// 并集
export type Concurrence<A, B> = A | B
// 交集
export type Intersection<A, B> = A extends B ? A : never
// 差集
export type Difference<A, B> = A extends B ? never : A
// 补集
export type Complement<A, B extends A> = Difference<A, B>typescript
// 例子 集合 T 相对于 null | undefined 的差集
type NonNullable<T> = T extends null | undefined ? never : T
type _NonNullable<T> = Difference<T, null | undefined>模式匹配工具类型
主要使用条件类型与 infer 关键字。
对函数类型签名的模式匹配
typescript
type FunctionType = (...args: any) => any
type Parameters<T extends FunctionType> = T extends (...args: infer P) => any ? P : never
type ReturnType<T extends FunctionType> = T extends (...args: any) => infer R ? R : any更进一步,比如只匹配第一个参数类型:
typescript
type Firstparameter<T extends FunctionType> = T extends (arg: infer P, ...args: any) => any ? P : never
type FuncFoo = (args: number) => void
type FooFirstParameter = Firstparameter<FuncFoo> // number
type FuncBar = (...args: string[]) => void
type BarFirstParameter = Firstparameter<FuncBar> // string对 Class 进行模式匹配
typescript
type ClassType = abstract new (...args: any) => any
type ConstructorParameters<T extends ClassType> = T extends abstract new (...args: infer P) => any ? P : never
type InstanceType<T extends ClassType> = T extends abstract new (...args: any) => infer R ? R : neverClass 的通用类型签名,实际上就是声明了可实例化(new)与可抽象(abstract)
typescript
export interface ClassType<TInstanceType = any> {
new (...args: any[]): TInstanceType
}拓展
提取数组第一个成员的工具类型
typescript
type FirstArrayItemType<T extends any[]> = T extends [infer R, ...any[]] ? R : never
// 加上字符串条件类型
type FirstArrayItemType2<T extends any[]> = T extends [infer R, ...any[]] ? R extends string ? R : never : never
type Tmp1 = FirstArrayItemType2<[100, 'Chocolate']> // never
type Tmp2 = FirstArrayItemType2<['Chocolate', 100]> // 'Chocolate'typescript
// ts 4,7 支持 infer 约束功能,能对特定类型进行提取
type FirstArrayItemType3<T extends any[]> = T extends [infer R extends string, ...any[]] ? R : neverContributors
文章作者:Choi Yang
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 ChoDocs!
