ts类型挑战【十九】

147 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 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 项就已经排除掉了 OO1 中重复的项了,接下来对 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