我有一个JS函数,它接受一个数组数组(长度相同,但类型不同)和一个键名数组(第一个参数中的每个数组一个),并将这些数组合并为一个数组对象。像这样:
const mergeArraysToSeries = (arrs, keys) => {
const merged = [];
for (let dataIndex = 0; dataIndex < arrs[0].length; dataIndex++) {
const el = keys.reduce((combined, currKey, keyIndex) => {
const val = arrs[keyIndex][dataIndex];
return { ...combined, [currKey]: val };
}, {});
merged.push(el);
}
return merged;
}
const example = mergeArraysToSeries([[1,2,3], ['a','b','c']], ['num', 'letter'])
// example = [{num: 1, letter: 'a'}, {num: 2, letter: 'b'}, {num: 3, letter: 'c'}]
有没有一种方法可以在TypeScript中编写此代码,从而在合并数组上提供良好的自动完成功能,并正确映射每个键的类型?对于上面的示例,我希望编译器知道example[0].num
的类型为'number'
我已经到达一个可以自动完成/编译器检查结果数组中每个项目的属性名称的地方,但是不确定如何为要通过的每个元素获取正确的类型。类型签名现在看起来像这样:
const mergeArrayToSeries = <K>(arrs: any[][], keys: (keyof K)[]): Record<keyof K, any>[] => ...
是否有一种很好的方法来删除传递的数组中的any
,并具有上述类型安全性?
谢谢!
编辑:如果可能,我希望此方法可用于任意数量的要合并的数组。
答案 0 :(得分:0)
您可以使用像这样的签名:
declare function mergeArraysToSeries<
T extends any[],
U extends any[],
P1 extends string,
P2 extends string
>(arrays: [T, U], properties: [P1, P2]): {
[K in P1]: T[number]
} & {
[K in P2]: U[number]
}[];
const example = mergeArraysToSeries([[1,2,3], ['a','b','c']], ['num', 'letter']); // example is { num: number; letter: string }[]
更新
如果需要支持两个以上的数组,则可以添加更多的重载。
declare function mergeArraysToSeries<T, U, P extends readonly string[]>(arrays: [T[], U[]], properties: P): { [K in P[0]]: T } & { [K in P[1]]: U }[]
declare function mergeArraysToSeries<T, U, V, P extends readonly string[]>(arrays: [T[], U[], V[]], properties: P): { [K in P[0]]: T } & { [K in P[1]]: U } & { [K in P[2]]: V }[]
declare function mergeArraysToSeries<T, U, V, W, P extends readonly string[]>(arrays: [T[], U[], V[], W[]], properties: P): { [K in P[0]]: T } & { [K in P[1]]: U } & { [K in P[2]]: V } & { [K in P[3]]: W }[]
const two = mergeArraysToSeries([[1, 2, 3], ['a', 'b', 'c']], ['num', 'letter'] as const)
const three = mergeArraysToSeries([[1, 2, 3], ['a', 'b', 'c'], ['foo', 'bar', 'baz']], ['num', 'letter', 'other'] as const)
const four = mergeArraysToSeries([[1, 2, 3], ['a', 'b', 'c'], ['foo', 'bar', 'baz'], [0, 0, 0]], ['num', 'letter', 'other', 'index'] as const)