精读《Diff, AnyOf, IsUnion...》

精读TypeScript挑战
本文深入探讨了TypeScript挑战中的几道中等难度题目,包括Diff、AnyOf、IsUnion等,通过实战演练提高理解与运用TS高级特性的能力。

解决 TS 问题的最好办法就是多练,这次解读 type-challenges Medium 难度 25~32 题。

精读

Diff

实现 Diff<A, B>,返回一个新对象,类型为两个对象类型的 Diff:

type Foo = {
  name: string
  age: string
}
type Bar = {
  name: string
  age: string
  gender: number
}

Equal<Diff<Foo, Bar> // { gender: number }

首先要思考 Diff 的计算方式,A 与 B 的 Diff 是找到 A 存在 B 不存在,与 B 存在 A 不存在的值,那么正好可以利用 Exclude<X, Y> 函数,它可以得到存在于 X 不存在于 Y 的值,我们只要用 keyof Akeyof B 代替 XY,并交替 A、B 位置就能得到 Diff:

// 本题答案
type Diff<A, B> = {
  [K in Exclude<keyof A, keyof B> | Exclude<keyof B, keyof A>]:
    K extends keyof A ? A[K] : (
      K extends keyof B ? B[K]: never
    )
}

Value 部分的小技巧我们之前也提到过,即需要用两套三元运算符保证访问的下标在对象中存在,即 extends keyof 的语法技巧。

AnyOf

实现 AnyOf 函数,任意项为真则返回 true,否则返回 false,空数组返回 false

type Sample1 = AnyOf<[1, '', false, [], {}]> // expected to be true.
type Sample2 = AnyOf<[0, '', false, [], {}]> // expected to be false.

本题有几个问题要思考:

第一是用何种判定思路?像这种判断数组内任意元素是否满足某个条件的题目,都可以用递归的方式解决,具体是先判断数组第一项,如果满足则继续递归判断剩余项,否则终止判断。这样能做但比较麻烦,还有种取巧的办法是利用 extends Array<> 的方式,让 TS 自动帮你遍历。

第二个是如何判断任意项为真?为真的情况很多,我们尝试枚举为假的 Case:0 undefined '' undefined null never []

结合上面两个思考,本题作如下解答不难想到:

type Falsy = '' | never | undefined | null | 0 | false | []
type AnyOf<T extends readonly any[]> = T extends Falsy[] ? false : true

但会遇到这个测试用例没通过:

AnyOf<[0, '', false, [], {}]>

如果此时把 {} 补在 Falsy

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值