【问题标题】:TypeScript: map object types containing string unions into return resultTypeScript:将包含字符串联合的对象类型映射到返回结果
【发布时间】:2021-07-20 20:10:39
【问题描述】:

这是这个问题的延伸:TypeScript: return a union of the input string array's literal values?

这个问题扩展了最后一个问题,将文字元组嵌入到对象上的任意键中,并将它们映射到输出键上。

function myfn<T extends string>(opts: { [key: string]: T[] }) {
  const out: ??? = {};
  for (const [key,val] of Object.entries(opts)) {
    out[key] = val[0];
  }
  return out;
}

const result = myfn({
  foo: ['a', 'b', 'c'],
  bar: ['x', 'y', 'z'],
})

// Expected: {
//   foo: 'a' | 'b' | 'c',
//   bar: 'x' | 'y' | 'z',
// }

myfn 中/上需要哪些类型才能获得预期的类型?

我知道这与Mapped Types 有关,但我无法弄清楚它应该是什么。

【问题讨论】:

    标签: typescript generics


    【解决方案1】:

    Freenode 上的用户 systemfault ##typescript 写了这个解决方案:

    
    type MyFnResult<T extends string, Options extends {readonly [k:string]: T[]}> = Options extends any? { [K in keyof Options]: Options[K][number] } : never
    
    function myfn<
      T extends string,
      Options extends {readonly [k:string]: T[] }
    >(opts: Options): MyFnResult<T, Options> {
      const out: Record<string, string> = {};
    
      for (const [key,val] of Object.entries(opts)) {
        out[key] = val[0];
      }
      return out as any
    }
    
    const result = myfn({
      foo: ['a', 'b', 'c'],
      bar: ['x', 'y', 'z'],
    })
    
    // Out type: {
    //   foo: 'a' | 'b' | 'c',
    //   bar: 'x' | 'y' | 'z',
    // }
    

    它有效。我有点不明白。但它有效。

    【讨论】:

    • 这与我的答案相同,我只是不希望 as any 演员获得完整答案。 MyFnResultMapToUnion 类型在功能上是相同的。
    • 他不使用as const,我认为这是主要区别,但很重要。
    【解决方案2】:

    目前没有完整的答案,但这是您正在寻找的类型:

    type MapToUnion<T extends { [key: string]: readonly string[] }> =
        {
            -readonly [K in keyof T]: T[K][number]
        }
    
    const opts = {
        foo: ['a', 'b', 'c'],
        bar: ['x', 'y', 'z'],
    } as const;
    
    type Mapped = MapToUnion<typeof opts>;
    
    // type Mapped = {
    //     foo: "a" | "b" | "c";
    //     bar: "x" | "y" | "z";
    // }
    

    【讨论】:

    • 没有as const有没有办法做到这一点?
    • @Steven 不是回答者,如果你不做const 断言并且让编译器推断opts 的类型,它将选择不合理的{foo: string[], bar: string[]},它完全忘记任何可能的字符串文字。 const 断言是迄今为止告诉编译器记住这些字符串文字的最简单方法。
    • 这可以做到,见stackoverflow.com/questions/67283229/…——我在这里要做的就是将它与类型映射结合起来,仅此而已。
    猜你喜欢
    • 2020-03-30
    • 1970-01-01
    • 1970-01-01
    • 2019-01-12
    • 2022-01-07
    • 1970-01-01
    • 2020-06-07
    • 2020-11-25
    • 1970-01-01
    相关资源
    最近更新 更多