首页 > 解决方案 > 为什么这个 TypeScript 类型会产生一个类似数组的结构,虽然它看起来像一个类似对象的类型?

问题描述

type Item<T extends string = string> = {
  item: T
}

type Card<T extends string = string> = string | Item<T>;

type Group<T extends Card[]> = {
  [K in keyof T]: T[K] extends Item<infer Name> ? Name : never
}

const group: Group<["book", { item: "SomeBookTitle" }]> =
  [null as never, "SomeBookTitle"]

根据类型Group的定义,我希望group有一个对象形状,也许是

const group = { "SomeBookTitle": "SomeBookTitle" }

它如何最终成为一个数组?

标签: typescript

解决方案


Group被定义为映射类型。尽管映射类型使用{}as 对象,但它们对输出类型有自己的规则。对于同态映射类型,如果输入类型是元组或数组,则原始类型的这个属性将是保留者。此行为是在 3.1 中通过此 PR引入的。

我不确定您为什么期望Group<["book", { item: "SomeBookTitle" }]>成为特定的对象类型({ "SomeBookTitle": "SomeBookTitle" }),该映射类型中的任何内容都表明它应该是,甚至在此 PR 之前,您最终会{ 0: never, 1: "SomeBookTitle" }得到一堆数组方法。

如果您想获得该类型,则映射类型必须如下所示:


type GroupKeys<T extends Card[]> = {
  [K in keyof T]: T[K] extends Item<infer Name> ? Name : never
}[number]

type Group<T extends Card[]> = {
  [K in GroupKeys<T>]: string // chose string not sure what you want here 
}


const group: Group<["book", { item: "SomeBookTitle" }]> = {
  SomeBookTitle: "",
}

游乐场链接


推荐阅读