【问题标题】:Creating a dictionary type from an array type从数组类型创建字典类型
【发布时间】:2022-06-22 17:56:30
【问题描述】:

假设有一个简单的对象类型X,以及一个创建显式类型数组XcreateXList的函数,如下所示:

type X = Readonly<{
  a: string
  b: string
}>

type XList = Readonly<X[]>

// TS workaround to create an explicitly-typed X
const createXList = <TXList extends XList>(xList: TXList): TXList => xList
*/

然后可以创建X 的显式类型数组,例如xList,如下所示:

const xList = createXList([
  { a: 'foo', b: 'bar' },
  { a: 'fizz', b: 'buzz' },
] as const)
/*
const xList: readonly [{
    readonly a: "foo";
    readonly b: "bar";
}, {
    readonly a: "fizz";
    readonly b: "buzz";
}]

问题是:如何为字典创建一个类型,其中每个键是ab 属性的串联,而值只是用于创建每个键的数组的值在字典中,同时仍保持显式键入。例如:

type XListToXDict<T extends XList> = { /* some magic */ }

type Test = XListToXDict<typeof xList>
/*
{
  "foobar": { a: "foo", b: "bar" };
  "fizzbuzz": { a: "fizz", b: "buzz" };
}
*/

因此,例如,为特定 X 创建密钥的类型是:

type XToKey<T extends X> = `${T['a']}${T['b']}`

注意事项:

人们会假设可以执行以下操作以至少提取字典的键(使用上面的XToKey):

type XListToKeys<T extends XList> = XToKey<T[number]>

但这会失败,因为它会生成ab 的所有可能组合(在xList 的特定情况下,即"foobar" | "foobuzz" | "fizzbar" | "fizzbuzz")。

然后是从数组中为字典中的每个值选择特定项目的挑战。

【问题讨论】:

    标签: typescript


    【解决方案1】:

    您可以使用映射类型并使用 as 重命名键名来实现此目的。

    type XListToXDict<T extends XList> = {
      [K in keyof T & `${bigint}` as T[K] extends { a: infer A, b: infer B } 
        ? `${A & string}${B & string}` 
        : never
      ]: T[K]
    }
    

    Playground

    【讨论】:

    • 谢谢托拜厄斯。 & `${bigint\}` 在这里做什么?
    • keyof 的数组会导致很多我们不需要的东西,比如lengthpop。 bigint 让我们只过滤数组索引,如 "0""1"
    • 这似乎是一个非常狡猾的解决方法,不是吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-08
    • 1970-01-01
    • 1970-01-01
    • 2021-12-09
    • 2011-06-23
    • 2019-05-19
    • 2011-10-27
    相关资源
    最近更新 更多