TypeScript:将包含字符串联合的对象类型映射到返回结果中

TypeScript:将包含字符串联合的对象类型映射到返回结果中,typescript,generics,Typescript,Generics,这是这个问题的延伸: 这个问题扩展了最后一个问题,将文本元组嵌入到对象上的任意键中,并将它们映射到输出键上 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 res

这是这个问题的延伸:

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

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(选项:{[key:string]:T[]}){ 常数out:?={}; for(对象项(opts)的常量[key,val]{ out[key]=val[0]; } 返回; } 常量结果=myfn({ foo:[a',b',c'], 条形图:['x','y','z'], }) //预期:{ //foo:‘a’|‘b’|‘c’, //酒吧:“x”|“y”|“z”, // } 要获得预期的类型,需要在
myfn
中/上输入哪些类型


我知道这和你有关系,但我不知道它到底应该是什么。

现在没有完整的答案,但这正是你要找的类型:

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";
// }
类型MapToUnion=
{
-只读[K in keyof T]:T[K][number]
}
常量选项={
foo:[a',b',c'],
条形图:['x','y','z'],
}作为常量;
类型Mapped=MapToUnion;
//类型映射={
//foo:“a”|“b”|“c”;
//酒吧:“x”|“y”|“z”;
// }

用户
系统故障
自由节点上
##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',
// }

键入MyFnResult=Options是否扩展了任何?{[K in keyof Options]:选项[K][number]}:从不
函数myfn<
T扩展字符串,
选项扩展了{readonly[k:string]:T[]}
>(选项:选项):MyFnResult{
const out:Record={};
for(对象项(opts)的常量[key,val]{
out[key]=val[0];
}
照常返回
}
常量结果=myfn({
foo:[a',b',c'],
条形图:['x','y','z'],
})
//输出类型:{
//foo:‘a’|‘b’|‘c’,
//酒吧:“x”|“y”|“z”,
// }

它起作用了。我一点也不懂。但是它是有效的。

有没有办法不用
作为常量来做这件事呢?@Steven不是回答者,如果你不做
常量
断言,让编译器推断
选项的类型
,它会选择不合理的
{foo:string[],bar:string[]}
,它完全忘记了任何可能的字符串文字<代码>常量
断言是告诉编译器记住这些字符串文字的最简单的方法。这是可以做到的,请看——我在这里尝试的是将其与类型映射结合起来,仅此而已。这与我的答案相同,我只是不想像任何
那样对完整答案进行转换。类型
myfnsult
MapToUnion
在功能上是相同的。His没有使用
作为常量,我认为这是主要的区别,但却是一个重要的区别。