目的
Github上的类型体操,让你写出更加优雅的TS类型定义,以及探寻TS中我们不熟悉的只是,让我们开始TS的类型挑战把~2022希望通过更文的方式来督促自己学习,每日三题,坚持日更不断~~
题目大纲
01. Medium ReplaceKey
题目要求
import { Equal, Expect } from '@type-challenges/utils'
type NodeA = {
type: 'A'
name: string
flag: number
}
type NodeB = {
type: 'B'
id: number
flag: number
}
type NodeC = {
type: 'C'
name: string
flag: number
}
type ReplacedNodeA = {
type: 'A'
name: number
flag: string
}
type ReplacedNodeB = {
type: 'B'
id: number
flag: string
}
type ReplacedNodeC = {
type: 'C'
name: number
flag: string
}
type NoNameNodeA = {
type: 'A'
flag: number
name: never
}
type NoNameNodeC = {
type: 'C'
flag: number
name: never
}
type Nodes = NodeA | NodeB | NodeC
type ReplacedNodes = ReplacedNodeA | ReplacedNodeB | ReplacedNodeC
type NodesNoName = NoNameNodeA | NoNameNodeC | NodeB
type cases = [
Expect<Equal<ReplaceKeys<Nodes, 'name' | 'flag', {name: number; flag: string}>, ReplacedNodes>>,
Expect<Equal<ReplaceKeys<Nodes, 'name', {aa: number}>, NodesNoName>>,
]
我的答案
type ReplaceKeys<U extends object, T, Y extends object> = {
[K in keyof U]: K extends T ? (K extends keyof Y ? Y[K] : never) : U[K];
};
知识点
- 如果一个 key 不想返回对应的值的时候,可以直接返回 never
- 直接 map 对象然后修改对应
key的类型即可
2. Medium RemoveIndex
题目要求
import { Equal, Expect } from '@type-challenges/utils'
type Foo = {
[key: string]: any;
foo(): void;
}
type Bar = {
[key: number]: any;
bar(): void;
}
type Baz = {
bar(): void;
baz: string
}
type cases = [
Expect<Equal< RemoveIndexSignature<Foo>, { foo(): void }>>,
Expect<Equal< RemoveIndexSignature<Bar>, { bar(): void }>>,
Expect<Equal< RemoveIndexSignature<Baz>, { bar(): void, baz: string }>>
]
我的解答
type RemoveIndexSignature<T extends any> = {
[K in keyof T as string extends K
? never
: number extends K
? never
: K]: T[K];
};
知识点
- 想要判断一个对象的 key 是否是泛类型,可以用
收窄的方式来做 key的定义也可以使用extends
3. Medium Percentage Parse
题目要求
import { Equal, Expect } from '@type-challenges/utils'
type Case1 = ['', '', '']
type Case2 = ['+', '', '']
type Case3 = ['+', '1', '']
type Case4 = ['+', '100', '%']
type Case5 = ['', '10', '%']
type Case6 = ['-', '99', '%']
type cases = [
Expect<Equal<PercentageParser<''>, Case1>>,
Expect<Equal<PercentageParser<'+'>, Case2>>,
Expect<Equal<PercentageParser<'+1'>, Case3>>,
Expect<Equal<PercentageParser<'+100%'>, Case4>>,
Expect<Equal<PercentageParser<'10%'>, Case5>>,
Expect<Equal<PercentageParser<'-99%'>, Case6>>,
]
我的解答
type Notion = "+" | "-" | "%";
type PercentageParser<
A extends string,
R extends any[] = []
> = A extends `${infer P}${infer T}`
? P extends Notion
? Handler2<T, [...R, P]>
: Handler2<A, [...R, ""]>
: Handler2<A, [...R, ""]>;
type Handler2<T extends string, R extends any[] = []> = T extends `${infer X}%`
? [...R, X, "%"]
: T extends string
? [...R, T, ""]
: [...R, "", ""];
知识点
- 字符串拼接的判断以及递归的使用