TypeScript 杂记二 《类型体操》
程序员文章站
2022-03-01 12:53:26
...
TypeScript 杂记二 《类型体操》
前提
type A = keyof any
// ===
type A = string | number | symbol
// infer 表示待推断的类型,如下内置类型
type ReturnType<T> = T extends (...args: any[]) => infer P ? P : any
type B = ReturnType<(value: string) => string>
// ===
type B = string
type Func = () => void
type C = keyof Func
// ===
type C = never
class Class {}
type C = keyof Class
// ===
type C = never
Pick<T, K>
type _Pick<T, K extends keyof T> = {
[P in K]: T[P]
}
Readonly
type _Readonly<T> = {
readonly [P in keyof T]: T[P]
}
Partial
type _Partial<T> = {
[P in keyof T]?: T[P]
}
Required
type _Required<T> = {
[P in keyof T]-?: T[P]
}
Record<T, K>
type _Record<T extends keyof any, K> = {
[P in T]: K
}
Exclude<T, K>
type _Exclude<T, K> = T extends K ? never : T
Extract<T, K>
type _Extract<T, K> = T extends K ? T : never
Omit<T, K>
type _Omit<T, K extends keyof any> = _Pick<T, _Exclude<keyof T, K>>
First
实现一个通用 First<T>
,它接受一个数组 T 并返回它的第一个元素的类型
type First<T extends any[]> = T extends [] ? never : T[0]
Last
实现一个通用 Last<T>
,它接受一个数组 T 并返回它的最后一个元素的类型
type First<T extends any[]> = T extends [...infer O, infer R] ? R : never
Readonly2<T, K>
实现一个通用的 Readonly2<T, K>
,K 指定应设置为 Readonly 的 T 的属性集。如果未提供 K,则应使所有属性都变为只读,就像普通的 Readonly一样
// 自己写的
type Readonly2<T, K extends keyof T = any> = K extends never
? Readonly<T>
: {
readonly [P in K]: T[P]
} & {
[P in Exclude<keyof T, K>]: T[P]
}
// 别人的精简版
type Readonly2<T, K extends keyof T = keyof T> = {
readonly [P in K]: T[P]
} & Omit<T, K>
DeepReadonly
实现一个通用的 DeepReadonly<T>
,它将对象的每个参数及其子对象递归地设为只读
// 满足简单数据结构
type DeepReadonly<T> = {
readonly [P in keyof T]: DeepReadonly<T[P]>
}
// 处理函数和类,原因查看前提的内容
type DeepReadonly<T> = keyof T extends never
? T
: {
readonly [P in keyof T]: DeepReadonly<T[P]>
}
Trim
type trimed = Trim<' Hello World '> // expected to be 'Hello World'
// 处理左侧的空格和换行,infer 请查看前提
// 一个一个递归处理
type TrimL<T extends string> = T extends `${' ' | '\t' | '\n'}${infer S}`
? TrimL<S>
: T
// 同理处理右侧
type TrimR<T extends string> = T extends `${infer S}${' ' | '\t' | '\n'}`
? TrimR<S>
: T
type Trim<T extends string> = TrimL<TrimR<T>>
// 整合起来
type Trim<T extends string> = T extends `${' ' | '\t' | '\n'}${infer L}`
? Trim<L>
: T extends `${infer R}${' ' | '\t' | '\n'}`
? Trim<R>
: T
vue
实现类似 Vue 的类型支持的简化版本
const instance = SimpleVue({
data() {
return {
firstname: 'Type',
lastname: 'Challenges',
amount: 10,
}
},
computed: {
fullname() {
return this.firstname + ' ' + this.lastname
},
},
methods: {
hi() {
alert(this.fullname.toLowerCase())
},
},
})
type ComputedReturn<T> = {
[K in keyof T]: T[K] extends () => infer R ? R : never
}
declare function SimpleVue<D, C, M>(options: {
data?(this: {}): D
computed?: C & ThisType<D & ComputedReturn<C> & M>
methods?: M & ThisType<D & ComputedReturn<C> & M>
}): D & ComputedReturn<C> & M
上一篇: drf---快速入门01