【问题标题】:How to type annotate object merging like rest operator does in typescript如何像打字稿中的休息运算符一样键入注释对象合并
【发布时间】:2023-03-14 08:40:01
【问题描述】:

我有这个功能可以合并任意数量的对象

function merge(...objs) {
  return objs.reduce((res, cur) => {
    for (const key in cur) {
      res[key] = cur[key]
    }
    return res;
  }, {});
}

一开始我以为这个函数不能进行类型注解,但后来我尝试了与我的merge函数非常相似的rest参数

const obj = {
  ...{ name: { ownName: 'Lewis' } },
  ...{ link: 'google.com' }
}
type Obj = typeof obj // I can happily get the Obj type

然后我想到了一个想法:当你事先不知道类型时,使用泛型。但是我如何定义其他泛型类型,例如 function merge<T, U, V...>(...objs: Array<T | U | V...>)

【问题讨论】:

    标签: javascript typescript merge typescript-generics


    【解决方案1】:

    推断rest 参数的最佳方法是使用variadic tuple types

    // credits goes to https://stackoverflow.com/a/50375286
    type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
        k: infer I
    ) => void
        ? I
        : never;
    
    function merge<T extends Record<PropertyKey, unknown>,
        Objs extends T[]
    >(...objs: [...Objs]):UnionToIntersection<Objs[number]>
    function merge<T extends Record<PropertyKey, unknown>,
        Objs extends T[]
    >(...objs: [...Objs]) {
        return objs.reduce((acc, obj) => ({
            ...acc,
            ...obj
        }), {});
    }
    
    const result = merge({ a: 1 }, { b: 2 })
    result.a // ok
    result.b // ok
    

    Playground

    Here,在我的博客中,你可以找到更多的推理技巧。

    至于返回类型。

    Objs[number] - 推断为数组中所有元素的联合 UnionToIntersection - 接受并合并它。

    附:尽量避免打字稿中的突变。 Here你可以找到如何处理它们的信息

    【讨论】:

    • 多么漂亮的技术,但我不明白为什么有两个函数声明,如果我删除上面的一个,TS会骂我。我只在函数重载下使用多个函数声明。
    • upper函数是bottom的重载。文档typescriptlang.org/docs/handbook/2/…
    • 我的答案比这个要好,但我猜
    • @captain-yossarian 是的,我知道它正在重载,但我不明白如果只有一个函数声明,为什么还要麻烦重载
    • @crazyones110 你可以摆脱重载,只在末尾使用类型断言UnionToIntersection&lt;Objs[number]&gt;。就个人而言,我更喜欢重载我的函数而不是断言。我认为它更安全,因为重载对于函数声明是双变量的。这取决于你
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-15
    • 2021-12-17
    • 2016-12-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多