You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何用[k in number]映射const数组无法得到预期联合类型?

TypeScript数组const断言下提取对应全名联合类型的问题

首先定义了只读数组:

const users = [
    { fname: "Samuel", lname: "Mathew", username: "sammt" },
    { fname: "Carlos", lname: "King", username: "kingg" },
] as const

需求是从中提取出类型:"Samuel Mathew" | "Carlos King"

尝试的写法及问题

尝试了以下映射写法,但返回的是所有fname与lname的笛卡尔积组合(比如"Samuel King"、"Carlos Mathew"这类不符合预期的项):

type TUserFullnames = {
  [k in number]: `${(typeof users)[k]["fname"]} ${(typeof users)[k]["lname"]}`;
}[number];

用户理解下面这种直接拼接联合类型的写法会得到全组合,但不明白为什么用number映射也会出现同样结果:

type TUserFullnames = `${(typeof users)[number]["fname"]} ${(typeof users)[number]["lname"]}`

但换成对象结构的写法却能正确得到对应用户的全名联合类型:

const users = {
    "sammt": { fname: "Samuel", lname: "Mathew" },
    "kingg": { fname: "Richie", lname: "Rich" },
} as const

type TUserFullnames = {
  [k in keyof typeof users]: `${(typeof users)[k]["fname"]} ${(typeof users)[k]["lname"]}`;
}[keyof typeof users];

问题原因

核心差异在于数组number索引和对象字符串键在TypeScript中的处理逻辑:

  • 对于as const断言的对象,keyof typeof users会解析为具体的字符串键联合类型("sammt" | "kingg"),映射时每个键对应唯一的用户对象,模板字符串会正确拼接该用户的fname和lname。
  • 对于as const断言的数组,typeof users是只读元组,但[k in number]中的number会被识别为通用数组索引类型,而非元组的具体数字字面量索引(0 | 1)。此时(typeof users)[k]会被解析为元组所有元素的联合类型,模板字符串会对联合类型的属性做笛卡尔积组合,最终得到所有可能的fname与lname搭配。

解决方法

要让TypeScript识别到映射的是元组的具体索引,需使用keyof typeof users作为映射键(只读元组的keyof会返回其数字字面量索引的联合类型):

const users = [
    { fname: "Samuel", lname: "Mathew", username: "sammt" },
    { fname: "Carlos", lname: "King", username: "kingg" },
] as const

type TUserFullnames = {
  [k in keyof typeof users]: `${(typeof users)[k]["fname"]} ${(typeof users)[k]["lname"]}`;
}[keyof typeof users];
// 结果:"Samuel Mathew" | "Carlos King"

这种写法下,每个k对应元组的具体索引,确保每个索引只关联唯一的用户对象,模板字符串就能正确拼接出对应用户的全名。

内容的提问来源于stack exchange,提问作者Developer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 03:24:55