我想在下面输入一个javascript函数。 此函数通过第二个参数重新映射第一个参数的属性名称。
我使用remap函数创建查询字符串参数。
例如,从{ param1: 1, param2: 2, param3: 3}
到?p1=1&p2=2&p3=3
。
/**
* @example
*
* const original = { a: 1, b: 'WOW', c: new Date(2019, 1, 1, 0, 0, 0) };
* const mapping = { a: 'hello', b: 'world', c: '!!!' };
*
* > remap(original, mapping);
* { hello: 1, world: 'WOW', '!!!': new Date(2019, 1, 1, 0, 0, 0) }
*/
const remap = (original, mapping) => {
const remapped = {};
Object.keys(original).forEach(k => {
remapped[mapping[k]] = original[k];
});
return remapped;
};
我在下面尝试了一个代码,但这是不正确的。
export const remap = <
T extends { [key: string]: any },
U extends { [P in keyof T]: string }
>(original: T, mapping: U) => {
const remapped: any = {};
Object.keys(original).forEach(k => {
remapped[mapping[k]] = original[k];
});
// Problems
// 1. remapped is declared as any, and cast required.
// 2. All values are declared ad any.
return remapped as { [P in keyof U]: any };
};
const remapped = remap(
{ a: 1, b: 'text', c: new Date() },
{ a: 'Hello', b: 'World', c: '!!!' }
);
console.info(remapped);
答案 0 :(得分:5)
您可以正确键入此字符,但是需要一些条件类型的魔术:
// Converts object to tuples of [prop name,prop type]
// So { a: 'Hello', b: 'World', c: '!!!' }
// will be [a, 'Hello'] | [b, 'World'] | [c, '!!!']
type TuplesFromObject<T> = {
[P in keyof T]: [P, T[P]]
}[keyof T];
// Gets all property keys of a specified value type
// So GetKeyByValue<{ a: 'Hello', b: 'World', c: '!!!' }, 'Hello'> = 'a'
type GetKeyByValue<T, V> = TuplesFromObject<T> extends infer TT ?
TT extends [infer P, V] ? P : never : never;
export const remap = <
T extends { [key: string]: any },
V extends string, // needed to force string literal types for mapping values
U extends { [P in keyof T]: V }
>(original: T, mapping: U) => {
const remapped: any = {};
Object.keys(original).forEach(k => {
remapped[mapping[k]] = original[k];
});
return remapped as {
// Take all the values in the map,
// so given { a: 'Hello', b: 'World', c: '!!!' } U[keyof U] will produce 'Hello' | 'World' | '!!!'
[P in U[keyof U]]: T[GetKeyByValue<U, P>] // Get the original type of the key in T by using GetKeyByValue to get to the original key
};
};
const remapped = remap(
{ a: 1, b: 'text', c: new Date() },
{ a: 'Hello', b: 'World', c: '!!!' }
);
// const remapped: {
// Hello: number;
// World: string;
// "!!!": Date;
// }