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

TypeScript中如何同时定义对象属性名与属性值的类型

写法失效原因

你写的[key in Car]: [key in Color]存在两个语法问题:

  • 映射类型的in遍历语法,只能用在类型定义的索引签名位置(也就是冒号左边定义属性名的位置),不能直接写在冒号右边的属性值位置。
  • 冒号右边的[key in Color]会被TS识别为元组类型定义,但元组内部不支持in遍历语法,且内外两层遍历都用了key作为变量名,存在命名冲突,属于非法类型语法,自然无法正常运行。

你本质的需求是约束属性值必须是Color联合类型的成员,根本不需要在值位置再做一次遍历,直接把值的类型指定为Color即可。

正确实现方案

根据你是否要求对象必须覆盖所有Car类型的成员,有两种常见实现:

  • 要求对象必须包含所有汽车品牌,不能缺省
    可以直接写映射类型,或者用TS内置的Record工具类型,两种写法完全等价:
    type Car = "toyota" | "mazda" | "suzuki" | "porsche";
    type Color = "white" | "black" | "yellow" | "red";
    
    // 手写映射类型
    const cars: {
      [brand in Car]: Color;
    } = {
      toyota: "red",
      mazda: "black",
      suzuki: "yellow",
      porsche: "white", // 缺任何一个品牌TS都会报缺少必填属性的错误
    };
    
    // 用Record简写
    const cars2: Record<Car, Color> = {
      toyota: "red",
      mazda: "black",
      suzuki: "yellow",
      porsche: "white",
    };
    
  • 只要求已写的属性名属于Car、属性值属于Color,不需要覆盖所有品牌
    给索引签名加可选标记,或者用Partial包裹Record即可:
    // 手写可选映射类型
    const cars: {
      [brand in Car]?: Color;
    } = {
      toyota: "red",
      porsche: "white", // 只写部分品牌不会报错
    };
    
    // Partial + Record简写
    const cars2: Partial<Record<Car, Color>> = {
      toyota: "red",
      porsche: "white",
    };
    

如果使用TS 4.9及以上版本,更推荐用satisfies运算符做类型校验,这种写法不会丢失对象字面量的字面量类型推导,使用更灵活:

const cars = {
  toyota: "red",
  porsche: "white",
} satisfies Partial<Record<Car, Color>>;

// 此时cars.toyota会被推导为精确的字面量类型"red",而不是宽泛的Color联合
// 如果写错属性名或属性值,TS会直接在编写时抛出错误
const badCars = {
  toyota: "blue", // 报错:"blue"不属于Color类型
  byd: "red", // 报错:"byd"不属于Car类型
} satisfies Partial<Record<Car, Color>>;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 02:36:08