代码之家  ›  专栏  ›  技术社区  ›  jmattheis zzz

重命名对象/接口类型安全的键

  •  3
  • jmattheis zzz  · 技术社区  · 6 年前

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

    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'}
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   jcalz    6 年前

    我可以再现你的问题 noted 在Github发行之前。那个问题被标为“已解决”,但这一部分显然没有。无论如何,这可能只是一个设计限制…typescript可以将具有泛型类型参数的对象表示为键的唯一方法是 mapped type 我怀疑typescript中的任何内容都会自动将对象文本解释为映射类型。我不知道Github中是否存在更合适的问题,或者是否应该有人打开一个问题。

    现在,你必须处理解决办法。如果您小心的话,您使用的类型是好的(断言返回值的类型)。A 轻微地 更安全的类型是逐个添加属性,如:

    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)
    

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