是否可以减少typescript中具有未知属性名称的泛型对象



是否可以通过对任何通用对象的属性求和,将两个对象归一

const A = {x:1, y:1, z:1}
const B = {x:2, y:2, z:2}
// result {x:3, y:3, z:3}

我希望得到一些功能

function reduceObjects<T extends {[readonly key: string]: number}>(previousObject:T, currentObject:T) => T

当我尝试这个解决方案

function reduceObjectsGeneric<T extends {readonly [key: string]: number}>(currentValue: T , previousValue: T): T {
const result = Object.assign({}, previousValue);

Object.keys(previousValue).forEach((k) => {
// eslint-disable-next-line functional/immutable-data
result[k]=previousValue[k]+currentValue[k]
})
return result
}

我在内环中得到以下错误

类型"string"不能用于索引类型"{}&T’.ts(2536(

实现这种行为的功能方式是什么?

功能方法是(但可能不是干净的(

function reduceObjects<T extends { [key: string]: number }>(a: T, b: T): T {
return Object.keys(a).reduce(
(acc, key) => Object.assign(acc, { [key]: a[key] + b[key] }),
b
);
}

首先,你得到对象"的键;a";使用CCD_ 1。然后使用JavaScript的CCD_ 2方法对键进行迭代;键";";acc";对象

通用reduceWith可以提供必要的支架:


type ReduceObjectsWith = <
V extends unknown, T = Record<PropertyKey, V>
>(fn: (acc: T, pair: [PropertyKey, V]) => T) => (...objs: T[]) => T;
type ReduceWithSum = ReduceObjectsWith<number>

const reduceObjectsWith = (fn) => (...objs) => objs.reduce(
(res, curr) => Object.entries(curr).reduce(fn, res), 
{},
);
const reduceWithSum = reduceObjectsWith(
(res, [key, value]) => ({ 
...res, 
[key]: value + (res[key] ?? 0),
}),
);
console.log(
reduceWithSum(
{x: 1, y: 1, z: 1},
{x: 2, y: 2, z: 2},
{x: -2, y: 2, z: 5},
{x: -1, y: 0, z: 32},
),
);

另一种使用只读函数方法传递大多数es-lint规则的方法:

function reducer<T extends {readonly [key: string]: unknown|number}>(object1: Partial<T>, object2: Partial<T>): T {
return Array.from(new Set([...Object.keys(object1),...Object.keys(object2)]).values()).reduce(
(p: T, c: string) => {
if ((object1[c] instanceof Object)) {
return { [c]: reducer(object1[c] as Partial<T>, (object2[c] ?? {}) as Partial<T>),...p}
}
const v1 = object1[c]??ZERO
const v2 = object2[c]??ZERO
return {[c]: (v1 as number)+(v2 as number),...p,}
}, {} as T
)
}

最新更新