typescript 类型体操 之 599-medium-merge

422 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第30天,点击查看活动详情

前言

在学习typescript的过程当中,有一个github库对其类型的学习特别有帮助,是一个有点类似于leetcode的刷题项目,能够在里面刷各种关于typescript类型的题目,在之前篇文章中,我们完成了中等的第二十二题,今天来做中等的第二十三题 531-medium-string-to-union

下面这个是类型体操github仓库:

type-challenges/type-challenges: Collection of TypeScript type challenges with online judge (github.com)

531-medium-string-to-union

image.png

import type { Equal, Expect } from '@type-challenges/utils'

type Foo = {
  a: number
  b: string
}
type Bar = {
  b: number
  c: boolean
}

type cases = [
  Expect<Equal<Merge<Foo, Bar>, {
    a: number
    b: number
    c: boolean
  }>>,
]

从README和测试用例中能够得出,我们需要实现一个工具函数 Merge 能够整合两个对象中的属性,并且第二个参数中的属性会覆盖掉第一个参数里面的同名属性。

利用 JS 进行模拟学习

JS 中存在很多种方法可以将对象进行拼接,主要可以通过解构,对象方法,或者循环遍历,这里就简单的举两个例子。

利用对象方法:

function merge1(obj1:any,obj2:any){
    return Object.assign(obj1,obj2)
}

image.png

利用循环:

function merge2(obj1:any,obj2:any){
    let obj3:any = {}
    for(let i of Object.keys(obj1)){
        obj3[i] = obj1[i]
    }
    for(let i of Object.keys(obj2)){
        obj3[i] = obj1[i]
    }
    return obj3
}

image.png

实现 Merge

那么根据 JS 的思路,在 TS 当中我们也能够通过多种方法来实现这个工具类型

Oimt

首先我们可以利用 TS 提供的 Omit 工具类型,先剔除掉第一个对象中含有的第二个对象的属性,然后将两个对象利用交叉类型进行合并。

type Merge2<F, S> = Omit<F,keyof S> & S

但是这期的测试似乎需要将类型铺平,而不是是直接这样。

image.png

image.png

所以我们还需要进行一次操作来将类型平铺:

type Merge<F, S> = {[P in keyof Merge2<F, S>]:Merge2<F, S>[P]}

type Merge2<F, S> = Omit<F,keyof S> & S

image.png

这样就能够通过测试了。

重映射

再者就是通过重映射来实现,在之前我们讲过重映射能够对映射类型的key值进行检验,不满足的就可以通过赋值为 never 进行排除,这也就可以应用到这个上面,将第一个对象中重复的键值进行剔除。

type Merge1<F, S> = {
    [P in keyof S]:S[P]
} & {
    [P in keyof F as P extends keyof S ? never : P]:F[P]
}

然后和第一种方法一样,需要做出平铺,这里就不再过多讲述,一样的操作就能够通过测试了。

知识点

关于上述提到了部分的知识点:

  1. Omit
  2. 映射类型
  3. 重映射
  4. 交叉类型

今天的题目设计的比较多的就是交叉类型,对于交叉类型在 TS 的对象处理中是很重要的概念,还不了解的可以优先去了解一下。

从集合的角度来看 Typescript 的类型 - 掘金 (juejin.cn)

总结

今天我们做完了中等的第二十三题,题目设计到了比较多的映射类型的细节以及交叉类型的使用,对于这两个知识之前都是有介绍过的,就看能不能灵活的进行运用。