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

TypeScript加as const后无法提取常量数组map属性键的原因及方案

问题1:为什么加as const断言后得到never类型

这是TypeScript类型系统对联合类型取keyof的固有规则,加上as const的类型窄化特性共同导致的:

  • 首先TypeScript中,keyof作用于联合类型时,返回的是所有联合成员共有的键的交集,而非所有键的并集,规则是keyof (A | B) = (keyof A) & (keyof B)。
  • 不加as const时,TypeScript会对数组元素类型做宽化处理:会自动给两个map对象补充不存在的键作为可选的undefined类型,此时typeof foobar[number]['map']的类型为{ a: {}, b?: undefined } | { b: {}, a?: undefined },两个类型共有的键是a和b,交集自然是'a' | 'b'。
  • 加as const后,TypeScript会严格保留字面量的原始结构,不会做额外的属性补全:此时typeof foobar[number]['map']的类型为{ readonly a: {} } | { readonly b: {} },两个类型没有公共的键,交集就是never。
    你观察到的「所有元素map属性子属性完全一致时返回正常」也符合这个规则:此时所有联合成员的键完全相同,交集就是键本身的联合。

问题2:提取只读结构的所有键联合类型

可以用分布式条件类型遍历联合的每个成员,分别取键之后再合并为联合,实现工具类型即可:

const foobar = [
  {
    name: 'foo',
    map: { a: {}, }
  },
  {
    name: 'bar',
    map: { b: {}, }
  }
] as const;

// 分布式条件类型工具:逐个处理联合的每个成员,取keyof后合并
type KeysOfUnion<T> = T extends T ? keyof T : never;

type FoobarMapItem = KeysOfUnion<typeof foobar[number]['map']>
// 此时FoobarMapItem类型为 "a" | "b"

这个工具类型对普通结构和as const生成的只读结构都生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 07:15:04