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

TypeScript对象字面量联合类型计算属性赋值异常问题

TypeScript函数内外类型检查差异问题解析

先看核心代码:

declare const GenderChoices: {
  readonly Male: "Male";
  readonly Female: "Female";
};
type GenderChoice = (typeof GenderChoices)[keyof typeof GenderChoices];

type Person = {
  id: number;
  name: string;
};
type PersonById = Record<number, Person>;

type PersonByGender = Partial<Record<GenderChoice, PersonById>>;

// 函数外部:报错
const gender: GenderChoice = "Male";
const obj = { [gender]: false };
const personByGender: PersonByGender = obj; // 类型不匹配报错

// 函数内部:正常通过
function testFunction(gender: GenderChoice) {
  const obj = { [gender]: false };
  const personByGender: PersonByGender = obj; // 无错误
}

原因拆解

1. 函数外部的类型推断逻辑

外部的gender是直接赋值"Male"的常量,TypeScript会自动类型收窄——把它的类型从GenderChoice联合类型缩小为具体的字面量类型"Male"。
因此,obj的类型会被精准推断为:

{ Male: boolean; }

而PersonByGender要求Male/Female属性的值必须是PersonById类型(或不存在),boolean类型和PersonById完全不兼容,所以触发类型报错。

2. 函数内部的类型推断逻辑

函数参数gender的类型是完整的GenderChoice联合类型(未被收窄),当用联合类型作为计算属性名时,TypeScript会把obj推断为具有联合类型所有键的可选索引签名:

{ [x in GenderChoice]?: boolean; }

此时TypeScript会采用宽松的兼容性规则:只要两个类型的索引签名结构一致(键的范围相同、都是可选),就允许赋值——哪怕值类型看起来不匹配。这是因为函数参数的联合类型是“通用”的,TypeScript无法确定具体会使用哪个键,因此放宽了检查标准。

解决方案

如果想让外部代码也通过类型检查,可以用两种方式调整:

  • 方式1:手动指定obj的类型

    const obj: PersonByGender = { [gender]: false };
    
  • 方式2:阻止gender的类型收窄

    const gender: GenderChoice = "Male" as GenderChoice;
    const obj = { [gender]: false };
    const personByGender: PersonByGender = obj;
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 05:58:34