持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第33天,点击查看活动详情
1. 引言
接着上一节中,接下来我们继续Ts中等篇的题型练习
https://github.com/type-challenges/type-challenges/blob/main/README.zh-CN.md 提供的TypeScript 类型体操姿势合集题型,目的是为了让大家更好的了解TS的类型系统,编写自己的类型工具,或者单纯的享受挑战的乐趣!
2. 题型
- Diff: 获取两个接口类型中的差值属性。
type Foo = {
a: string;
b: number;
}
type Bar = {
a: string;
c: boolean
}
type Result1 = Diff<Foo,Bar> // { b: number, c: boolean }
type Result2 = Diff<Bar,Foo> // { b: number, c: boolean }
思路: 首先要选出两个对象的差值类型,就确定需要类似Exclude 获取两个联合类型的差值,注:当联合类型合并时候最后返回的联合类型会过滤相同属性如Demo事例;因为不知道传入的形参那个属性多,所以采用分别ExcludeVal两次形参获取最全的联合键值,在通过类型推导获得对应键值。 解答:
type SSSRR<T,T1> = T | T1
type Demo = SSSRR<'a' | 'b','b' | 'c'> // type Demo = "a" | "b" | "c"
type ExcludeVal<M, N,KM = keyof M,KN = keyof N> = KM extends KN ? never : KM
type Diff<M, N> = {
[P in (ExcludeVal<M, N> | ExcludeVal<N, M>)]: P extends keyof M ? M[P] : P extends keyof N ? N[P] : never
}
type Demo2 = Diff<Foo, Bar> // type Demo2 = {gender: number;}
type Demo3 = Diff<Bar, Foo> // type Demo2 = {gender: number;}
type Demo4 = Diff<Foo, Coo> // type Demo4 = {age: string;gender: number;}
type Demo5 = Diff<Coo, Foo> // type Demo5 = {age: string;gender: number;}
- AnyOf:在类型系统中实现类似于 Python 中 any 函数。类型接收一个数组,如果数组中任一个元素为真,则返回 true,否则返回 false。如果数组为空,返回 false。
type Sample1 = AnyOf<[1, '', false, [], {}]> // expected to be true.
type Sample2 = AnyOf<[0, '', false, [], {}]> // expected to be false.
思路: 定义一个包含所有false 场景的联合类型集(注意:如Drr 例子所述[] extends {} 走的是true 分支,所以但我们要判断一个对象是否为空的时候要使用 {[p:string]:never}),在使用extends 判断语句执行时,把目标对象和一个包含所有false场景的数组进行对比就可返回想要结果。 解答:
type Drr = [] extends {} ? true : false // type Drr = true
type IsTruth = 0 | '' | [] | false | {[p:string]:never}
type AnyOf<T extends readonly any[]> = T extends Array<IsTruth> ? false : true
type Demo = AnyOf<[1, 'test', true, [1]]> // type Demo = true
type Demo2 = AnyOf<[1, '', false, [], {}]> // type Demo2 = true
type Demo3 = AnyOf<[0, 'test', false, [], {}]> // type Demo3 = true
type Demo4 = AnyOf<[0, '', true, [], {}]> // type Demo4 = true
type Demo5 = AnyOf<[0, '', false, [1], {}]> // type Demo5 = true
type Demo6 = AnyOf<[0, '', false, [], { name: 'test' }]> // type Demo6 = true
type Demo7 = AnyOf<[0, '', false, [], { 1: 'test' }]> // type Demo7 = true
type Demo8 = AnyOf<[0, '', false, [], { name: 'test' }, { 1: 'test' }]> // type Demo8 = true
type Demo9 = AnyOf<[0, '', false, [], {}]> // type Demo9 = false
type Demo10 = AnyOf<[]> // type Demo10 = false
- IsNever:实现一个类型IsNever,它接受输入类型t。如果的类型解析为never,则返回true,否则返回false。
type A = IsNever<never> // expected to be true
type B = IsNever<undefined> // expected to be false
type C = IsNever<null> // expected to be false
type D = IsNever<[]> // expected to be false
type E = IsNever<number> // expected to be false
思路: 这道题怎么说呢,经过下述实例证明只有 never[] extends never[] 才会为true,其他都是false,所以就先这么记吧,23333
type TestFun<T,N> = T extends N ? true : false
type Test1 = TestFun<''[],['']> // type Test1 = false
type Test1_1 = TestFun<''[],''> // type Test1_1 = false
type Test2 = TestFun<undefined[],[undefined]> // type Test2 = false
type Test3 = TestFun<never[],[never]> // type Test3 = false
type Test4 = TestFun<''[],never[]> // type Test4 = false
type Test5 = TestFun<never[],never[]> // type Test5 = true
type Test6 = TestFun<unknown[],never[]> // type Test6 = false
type Test7 = TestFun<any[],never[]> // type Test7 = false
解答:
type IsNever<T> = T[] extends never[] ? true : false
type Demo = IsNever<never> // type Demo = true
type Demo2 = IsNever<never | string> // type Demo2 = false
type Demo3 = IsNever<''> // type Demo3 = false
type Demo4 = IsNever<undefined> // type Demo4 = false
type Demo5 = IsNever<null> // type Demo5 = false
type Demo6 = IsNever<[]> // type Demo6 = false
type Demo7 = IsNever<{}> // type Demo7 = false