首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TypeScript:在类型安全中重新映射对象属性

TypeScript:在类型安全中重新映射对象属性
EN

Stack Overflow用户
提问于 2019-04-01 19:32:42
回答 1查看 2K关注 0票数 3

我想做的是

我想在下面输入一个javascript函数。此函数通过第二个参数重新映射第一个参数的属性名称。

我使用remap函数来创建查询字符串参数。例如,从{ param1: 1, param2: 2, param3: 3}?p1=1&p2=2&p3=3

代码语言:javascript
复制
/**
 * @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;
};

我的不完善的代码

我尝试了下面的代码,但这是不可靠的。

代码语言:javascript
复制
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);
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-04-01 19:51:46

你可以正确地输入这段代码,但这需要一些条件类型魔法:

代码语言:javascript
复制
// 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;
// }
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55454125

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档