【问题标题】:Rename keys of an object/interface typesafe重命名对象/接口类型安全的键
【发布时间】:2018-06-15 20:43:27
【问题描述】:

我想使用映射函数动态重命名键。为此,我做了这个:

interface DateRange {
    startDate: string;
    endDate: string;
}

function format<K extends string>(range: DateRange, mapping: {[X in keyof DateRange]: K}): {[P in K]: string} {
    return {
        [mapping.startDate]: range.startDate,
        [mapping.endDate]: range.endDate,
    };
}

当我使用as {[P in K]: string} 强制转换此函数的返回值时,一切正常,但没有强制转换则无法编译。

错误信息:

TS2322: Type '{ [x: string]: string; }' is not assignable to type '{ [P in K]: string; }'.

从我看到DateRange接口的两个键都使用了,所以返回值的键应该都是K类型的。

函数必须是什么样子才不需要强制转换?

调用示例:

const formatted = format(
    {startDate: 'startDateValue', endDate: 'endDateValue'}, 
    {startDate: 'start', endDate: 'end'}
);
// formatted = {end: 'endDateValue', start: 'startDateValue'}

【问题讨论】:

    标签: javascript typescript typescript2.0


    【解决方案1】:

    我可以重现您的问题,并且之前在 GitHub 问题中似乎是 noted。该问题已被标记为“已修复”,但这部分显然没有。无论如何,这可能只是一个设计限制...... TypeScript 可以使用泛型类型参数作为键来表示对象的唯一方法是使用 mapped type,我怀疑 TypeScript 中的任何内容都会将对象文字解释为映射自动输入。我不知道 GitHub 中是否存在更合适的现有问题,或者是否应该有人打开一个。

    现在,您必须处理变通方法。如果你小心的话,你使用的那个很好(断言返回值的类型)。 稍微更多类型安全的方法是逐个添加属性,如:

    function format<K extends string>(
      range: DateRange, 
      mapping: { [X in keyof DateRange]: K }
    ): { [P in K]: string } {
      const ret = {} as { [P in K]: string }; // assertion
      ret[mapping.startDate] = range.startDate; // safer
      ret[mapping.endDate] = range.endDate; // safer
      return ret;
    }
    

    如果您遗漏一个属性,它仍然不会抱怨,但它会阻止您添加随机的其他字符串值计算属性:

      const badProp: string = "uh oh"
      return {
        [mapping.startDate]: range.startDate,
        [mapping.endDate]: range.endDate,
        [badProp]: "whoops" // no error
      } as { [P in K]: string };
    

      const badProp: string = "uh oh"
      const ret = {} as { [P in K]: string };
      ret[mapping.startDate] = range.startDate;
      ret[mapping.endDate] = range.endDate;
      ret[badProp] = "whoops"; // error (implicit any)
    

    不过,这对你来说可能不值得,而且你的类型断言是合理的。希望这会有所帮助。祝你好运!

    【讨论】:

      猜你喜欢
      • 2019-03-13
      • 2017-08-18
      • 2020-10-14
      • 1970-01-01
      • 2011-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多