根据一些业务规则,我创建了一个聚合函数,需要正确输入.

函数(JS):

它需要:

  • 初始对象.
  • n件物品.
export function aggregateObjects(initialObject, ...newObjects) {
  const aggregate = (objectA, objectB) => {
    return Object.keys(objectB).reduce(
      (acc, key) => ({
        ...acc,
        [key]: [...(acc[key] ?? []), ...(objectB[key] ?? [])],
      }),
      objectA
    );
  };

  return newObjects.reduce(
    (aggregatedObjects, newObject) => aggregate(aggregatedObjects, newObject),
    initialObject
  );
}

如何使用它(Typescript ):

下面是传递给aggregateObjects的两个新对象的示例,但它应该适用于5、10、...

const initialObject = {
  a: [objectOfType1],
};

const newObject1 = {
  a: [objectOfType2],
  b: [objectOfType1],
};

const newObject2 = {
  c: [objectOfType1, objectOfType2],
};

const result = aggregateObjects(initialObject, [newObject1, newObject2]);

我们所期望的(Typescript ):

根据前面的示例,我们预期结果如下:

  • a的类型应为ObjectType1ObjectType2的array.
  • b的类型应为ObjectType1的array.
  • c的类型应为ObjectType1ObjectType2的array.
type Result = {
  a: (ObjectType1 | ObjectType2)[];
  b: ObjectType1[];
  c: (ObjectType1 | ObjectType2)[];
};

我try 了什么(Typescript ):

当然,它不起作用:

  • 内部aggregate看起来没问题(即使有一些与传播相关的问题).
  • 在外部,我没有找到正确输入返回值的解决方案.

请注意,CombineObjs是受https://dev.to/svehla/typescript-how-to-deep-merge-170c启发的TS帮助器

export function aggregateObjects<T extends object, U extends any[]>(
  initialObjects: T,
  ...newObjects: U
) {
  const aggregate = <A extends object, B extends object>(
    objectA: A,
    objectB: B
  ): CombineObjs<A, B> => {
    return (Object.keys(objectB) as Array<keyof B>).reduce(
      (acc, key) => ({
        ...acc,
        [key]: [
          // @ts-ignore
          ...(acc[key as keyof CombineObjs<A, B>] ?? []),
          // @ts-ignore
          ...(objectB[key] ?? []),
        ],
      }),
      objectA as unknown as CombineObjs<A, B>
    );
  };

  return newObjects.reduce(
    (aggregatedObjects, newObject) => aggregate(aggregatedObjects, newObject),
    initialObjects
  );
}

感谢您的解决方案.

推荐答案

下面是该函数的类型.

type UnionToIntersection<U> =
  (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;

function aggregateObjects<
  T extends Record<string, any[]
>[]>(objects: [...T]): { 
  [K in keyof UnionToIntersection<T[number]>]: (T[number] extends infer U ? 
    U extends Record<K, (infer V)[]> 
      ? V
      : never
    : never)[]
} {
    return {} as any
}

我看不出有任何理由将initialObject作为单独的参数,因为它的处理方式似乎与其他对象完全一样.

const initialObject = {
  a: ["objectOfType1"],
};

const newObject1 = {
  a: [23],
  b: ["objectOfType1"],
};

const newObject2 = {
  c: ["objectOfType1", 23],
};

const result = aggregateObjects([initialObject, newObject1, newObject2]);
// const result: {
//   a: (string | number)[];
//   b: string[];
//   c: (string | number)[];
// }

Playground

Typescript相关问答推荐

如何根据数据类型动态注入组件?

React组件数组及其props 的类型定义

如何使打包和拆包功能通用?

对深度对象键/路径进行适当的智能感知和类型判断,作为函数参数,而不会触发递归类型限制器

webpack错误:模块找不到.当使用我的其他库时,

在NextJS中获得Spotify Oauth,但不工作'

具有泛型类型和缺省值的键

如何编写一个类型脚本函数,将一个对象映射(转换)为另一个对象并推断返回类型?

如何调整对象 struct 复杂的脚本函数的泛型类型?

带下拉菜单的Angular 响应式选项卡

是否可以从函数类型中创建简化的类型,go 掉参数中任何看起来像回调的内容,而保留其余的内容?

MatTool提示在角垫工作台中不起作用

TypeScrip:使用Union ToInterval辅助对象,但保留子表达式

Typescript -返回接口中函数的类型

为什么特定的字符串不符合包括该字符串的枚举?

为什么TS2339;TS2339;TS2339:类型A上不存在属性a?

为什么类型脚本使用接口来声明函数?他的目的是什么.

如何在Reaction Native中关注屏幕时正确更新状态变量?

在ts中获取级联子K类型?

必须从注入上下文调用Angular ResolveFn-inject()