一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第21天,点击查看活动详情。
题目二十九:diff
// template.ts
type Diff<O, O1> = any
// test-cases.ts
import type { Equal, Expect } from '@type-challenges/utils'
type Foo = {
name: string
age: string
}
type Bar = {
name: string
age: string
gender: number
}
type Coo = {
name: string
gender: number
}
type cases = [
Expect<Equal<Diff<Foo, Bar>, { gender: number }>>,
Expect<Equal<Diff<Bar, Foo>, { gender: number }>>,
Expect<Equal<Diff<Foo, Coo>, { age: string; gender: number }>>,
Expect<Equal<Diff<Coo, Foo>, { age: string; gender: number }>>,
]
获取两个接口类型中的差值属性。
代码实现
- 原代码
type Diff<O, O1> = any
- 使用
in keyof进行数组遍历
type Diff<O, O1> = {
[P in keyof O]: ...
}
- 遍历中,需要拿出下面的项
O中有的,并且O1中没有O1中有的,并且O中没有
type Diff<O, O1> = {
[P in Exclude<keyof O, keyof O1> | Exclude<keyof O1, keyof O>]: ...
}
此时遍历的所有 key 项就已经排除掉了 O 和 O1 中重复的项了,接下来对 value 进行处理
- 如果当前遍历项存在于
O,则返回其对应的值
type Diff<O, O1> = {
[P in Exclude<keyof O, keyof O1> | Exclude<keyof O1, keyof O>]: P extends keyof O
? O[P]
: ...
}
- 接下来判断当前遍历项是否存在于
O1,如果存在则返回其对应的值
type Diff<O, O1> = {
[P in Exclude<keyof O, keyof O1> | Exclude<keyof O1, keyof O>]: P extends keyof O
? O[P]
: P extends keyof O1
? O1[P]
: never
}
最后返回的 never 不会执行到,因为我们最开始对 key 的过滤就已经确定了它一定是在 O 或者 O1 中的
题目三十:anyof
// template.ts
type AnyOf<T extends readonly any[]> = any
// test-cases.ts
import type { Equal, Expect } from '@type-challenges/utils'
type cases = [
Expect<Equal<AnyOf<[1, 'test', true, [1], { name: 'test' }, { 1: 'test' }]>, true>>,
Expect<Equal<AnyOf<[1, '', false, [], {}]>, true>>,
Expect<Equal<AnyOf<[0, 'test', false, [], {}]>, true>>,
Expect<Equal<AnyOf<[0, '', true, [], {}]>, true>>,
Expect<Equal<AnyOf<[0, '', false, [1], {}]>, true>>,
Expect<Equal<AnyOf<[0, '', false, [], { name: 'test' }]>, true>>,
Expect<Equal<AnyOf<[0, '', false, [], { 1: 'test' }]>, true>>,
Expect<Equal<AnyOf<[0, '', false, [], { name: 'test' }, { 1: 'test' }]>, true>>,
Expect<Equal<AnyOf<[0, '', false, [], {}]>, false>>,
Expect<Equal<AnyOf<[]>, false>>,
]
在类型系统中实现类似Python的'any'函数。该类型接受数组,如果数组中的任何元素为true,则返回'true'。如果数组为空,则返回'false'。
测试用例
通过测试用例可知:
- 该函数传入一个数组
- 如果数组中全部的值都是:
0 | '' | false | [] | {}这几个值中的,就返回false - 否则返回
true
代码实现
- 原代码
type AnyOf<T extends readonly any[]> = any
- 将上述会返回
false的值设置为联合类型
type AnyOfFalse = 0 | "" | false | [] | { [key: string]: never }
type AnyOf<T extends readonly any[]> = any
- 使用
T[number]进行数组遍历
type AnyOfFalse = 0 | "" | false | [] | { [key: string]: never }
type AnyOf<T extends readonly any[]> = T[number]
- 如果
T[number]全部的值都继承自AnyOfFalse,则返回false,否则返回true(至少有一个不继承自AnyOfFalse)
type AnyOfFalse = 0 | "" | false | [] | { [key: string]: never }
type AnyOf<T extends readonly any[]> = T[number] extends AnyOfFalse ? false : true