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

如何实现TypeScript中关联对象属性与值的条件泛型类型

在TypeScript中实现关联prop和value类型的泛型类型PartOfObjectType

你想要的是让prop和value的类型严格绑定——选了对象里存在的某个键,value就必须匹配该键对应的类型,同时禁止使用不存在的键,且两个属性必须同时存在。之前的两种写法都没实现这种类型关联:

  • 写法1里prop是keyof ObjectType的联合类型,TypeScript无法将单个prop的取值和value的类型一一对应,因此ObjectType[prop]会直接报错;
  • 写法2的value是所有值类型的联合(比如string | number),不管选哪个prop,value都可以是任意值类型,达不到关联约束的效果。

下面给出两种可行的实现方案:

方法1:双泛型参数绑定具体键

把泛型拆成两个参数,第二个参数用来指定prop的具体类型,让value严格对应该键的类型:

interface CarType {
  name: string;
  price: number;
}

type PartOfObjectType<ObjectType, K extends keyof ObjectType> = {
  prop: K;
  value: ObjectType[K];
};

// 使用示例
const carName: PartOfObjectType<CarType, 'name'> = { prop: 'name', value: 'Tesla' }; // 合法
const carPrice: PartOfObjectType<CarType, 'price'> = { prop: 'price', value: 300000 }; // 合法
// const errorKey: PartOfObjectType<CarType, 'color'> = { prop: 'color', value: 'red' }; // 报错:'color'不是CarType的键
// const errorValue: PartOfObjectType<CarType, 'price'> = { prop: 'price', value: '300000' }; // 报错:value应为number类型

这种方式需要显式指定第二个泛型参数,类型约束明确,适合需要固定某个键的场景。

方法2:生成所有合法键值对的联合类型

如果不想显式指定键,希望TypeScript自动推导prop和value的关联,可以遍历ObjectType的所有键,生成每个键对应的类型后合并成联合类型:

interface CarType {
  name: string;
  price: number;
}

type PartOfObjectType<ObjectType> = {
  [K in keyof ObjectType]: {
    prop: K;
    value: ObjectType[K];
  }
}[keyof ObjectType];

// 使用示例
const carName: PartOfObjectType<CarType> = { prop: 'name', value: 'Tesla' }; // 合法
const carPrice: PartOfObjectType<CarType> = { prop: 'price', value: 300000 }; // 合法
// const errorKey: PartOfObjectType<CarType> = { prop: 'color', value: 'red' }; // 报错:'color'不是合法prop
// const errorValue: PartOfObjectType<CarType> = { prop: 'price', value: '300000' }; // 报错:value类型不匹配

这种方式无需额外指定键,编辑器会自动根据你输入的prop值,提示value必须对应的类型,完全满足你的三个约束要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 13:18:13