ts 里面类型 <泛型> 太重要,很多机制也很迷惑。所以使用 type-challenges 来帮助我辅助练习。
// 4-easy-pick
type MyPick<T, K extends keyof T> = { [P in K]: T[P] }
// 7-easy-readonly
type MyReadonly<T> = {
readonly [P in keyof T]: T[P]
}
// 11-easy-tuple-to-object
type TupleToObject<T extends readonly string[]> = {
[key in T[number]]: key
}
// 这个 case 认识到了原来数组可以通过 T[number] 来获取里面的 value
// 14-easy-first
type First<T extends any[]> = T[0]
// 18-easy-tuple-length
type Length<T extends readonly unknown[]> = T['length']
// 这个 case 让我知道,原来在设定泛型 T 类型之后,可以使用里面的一些属性和方法
// 43-easy-exclude
type MyExclude<T, U> = T extends U ? never : T
type testCase = MyExclude<'a' | 'b' | 'c', 'c' | 'd' | 'f'>
// 这个视角,先把 U 代入 extends 右边
// 然后 T 这个联合类型 从左到右
// 'a' => T == 'a'
// 'b' => T == 'b'
// 'c' => never
// result = 'a' | 'b' | never = 'a' | 'b'
// 268-easy-if
type If<C extends boolean, T, F> = C extends true ? T : F
// 这里要声明 condition C 为 boolean,不然 null 这些非 true 不会报错
// 3057-easy-push
type Push<T, U> = T extends [...infer R] ? [...R, U] : never
// infer R 和 [...infer R] ,左边那个不知道是啥,右边那个是个数组
// 3060-easy-unshift
type Unshift<T, U> = T extends [...infer R] ? [U, ...R] : never
// 问题和 533-easy-concat 一样,为啥不能用 R['unshift'](U) 呢?
// 189-easy-awaited
type Awaited<T extends Promise<unknown>> = T extends Promise<infer R>
? R
: never
// 非常实用,从这个case,认识了 infer 这个关键词
// 仅条件类型的 "extends" 子句中才允许 "infer" 声明。
// 为什么 infer 只能放在右边呢? 推测还是需要类型吧.
// 533-easy-concat
type Concat<T extends unknown[], U extends unknown[]> = [...T, ...U]
// 一开始没想到,ts里也能用数组展开符号,问题来了
// 为什么不能否写成这样呢?笑~
type Concat<T extends unknown[], U extends unknown[]> = T['concat'](U)
// 898-easy-includes
// 最令人疑惑的题目来了
type Includes<T extends readonly any[], U> = {
[K in T[number]]: true
}[U] extends true
? true
: false
// 这个思路,一个严重的问题,这个实际上做的是,数组转对象,key为数组对应索引的值,默认附值为 ture
// 然后去判断 U 这个 key 是否为 true, true 就说明有这个类型,false则无
// 但是case报错了
Expect<Equal<Includes<[false, 2, 3, 5, 6, 7], false>, true>>
// 结果为 false
// debug
type testCase = Includes<[false, 2, 3, 5, 6, 7], false>
// false
type part1<T extends readonly any[], U> = {
[K in T[number]]: true
}
type t = part1<[false, 2, 3, 5, 6, 7], false>
type t = {
6: true;
2: true;
3: true;
5: true;
7: true;
}
// 为啥 false 被去掉了?
// 这个答案是issue里面找到的
type Includes<T extends readonly any[], U> = T extends [infer L, ...infer R]
? [U, L] extends [L, U]
? true
: Includes<R, U>
: false
// 结果
Expect<Equal<Includes<[{ a: 'A' }], { readonly a: 'A' }>, false>>
Expect<Equal<Includes<[{ readonly a: 'A' }], { a: 'A' }>, false>>
// 这 2 个 readonly 的 case 挂了
// 这个答案看不懂得地方在于
// T extends [infer L, ...infer R]
// [U, L] extends [L, U]
// 和 Includes 泛型递归
// 焦头烂额
// 3312-easy-parameters
type MyParameters<T extends (...args: any[]) => any> = T extends (
...args: infer R
) => any
? R
: never
// 这里为什么 infer R ,和 [...infer R] 都可以?
type MyParameters<T extends (...args: any[]) => any> = T extends (
...args: [...infer R]
) => any
? R
: never
简单的泛型体操,就搞得焦头烂额,平时自己使用的声明,还是太简单了,2 个领悟: