首页 > 解决方案 > TypeScript 与数组的交集

问题描述

我正在使用 lodashmerge合并两个对象。lodash 的类型(https://github.com/DefinitelyTyped/DefinitelyTyped/blob/bab9c9aef2477d222f014a25ce86585af76c3a5c/types/lodash/common/object.d.ts#L1718)仅依赖于在数组方面有一些缺点的交集类型。

假设我想合并具有这些类型的对象

interface One {
  str: string;
  arr: Array<{ foo: string }>;
}

interface Two {
  num: number;
  arr: Array<{ bar: string }>;
}

当这些对象与 lodash 合并时merge,生成的形状是

interface Merged {
  str: string;
  num: number;
  arr: Array<{ foo: string; bar: string }>;
}

但这不是交集类型的工作方式(这里的基本原理)。你最终得到的类型arrArray<{ foo: string; }> & Array<{ bar: string }>有这个问题:

declare const test: Array<{ foo: string }> & Array<{ bar: string }>;
test.forEach((item) => item.bar); // Property 'bar' does not exist on type '{ foo: string; }'.(2339)

游乐场链接

可以为数组merge定义更好的Array<A>类型Array<B>吗?它必须是某种递归映射类型,但我没有任何运气写一个。Array<A & B>Array<A> & Array<B>

标签: typescripttypeslodash

解决方案


我认为我们可以创建一种递归地规范化数组的类型。

type NomalizeArrays<T> = {
    [P in keyof T]: T[P] extends any[] ? Array<NomalizeArrays<T[P][number]>> : NomalizeArrays<T[P]>
}

我们可以通过 中的任何路口T。除了数组,我们大多不考虑结构。对于数组,我们T[P][number]将其作为对象类型的交集。

它似乎无法按预期工作,如果您发现任何问题,请告诉我:


let r = _.merge({
    arr: [{ foo : "A"}],
    str: ""
},  {
    arr: [{ bar: "B"}],
    num: 1
})

r.arr.forEach(x => x.bar + x.foo);

let r2 = _.merge({
    arr: [{ outerA: "", nested: [{ foo: "" }]}]
}, {
    arr: [{ outerB: "", nested: [{ bar: "" }]}]
})

r2.arr.forEach(x => {
    x.outerA
    x.outerB
    x.nested.map(xx => xx.bar  +  xx.foo)
});

游乐场链接


推荐阅读