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

如何在TypeScript中实现对象属性赋值的类型匹配校验?

TypeScript 实现属性值赋值的类型校验

我想要编写一个updateValue函数,该函数接收目标对象a、a的属性键aKey,以及对象b、b的属性键bKey,将b[bKey]的值赋值给a[aKey]。

尝试的初始代码如下:

const updateValue = <T1, T1Key extends keyof T1, T2, T2Key extends keyof T2>(
  a: T1,
  aKey: T1Key,
  b: T2,
  bKey: T2Key
) => {
  a[aKey] = b[bKey];
  // 此处报错:
  // 'T1' could be instantiated with an arbitrary type which could be unrelated to 'T2'.ts(2322)
};

const a = {
  a: 1,
  b: 'b',
};

const b = {
  c: 2,
  d: 'd',
};

预期合法的调用:

updateValue(a, 'a', b, 'c'); // 合理,a.a(number)和b.c(number)类型匹配

需要禁止的非法调用:

updateValue(a, 'b', b, 'c'); // 应该被禁止,a.b(string)和b.c(number)类型不匹配

初始代码仅校验属性是否存在,无法约束属性值的类型兼容性,以下是解决方案:

方法一:通过工具类型筛选兼容键

首先定义一个工具类型,筛选出对象中属性值可赋值给目标类型的键:

type AssignableKey<TObj, TTarget> = {
  [K in keyof TObj]: TObj[K] extends TTarget ? K : never;
}[keyof TObj];

然后修改updateValue函数,用这个工具类型约束bKey的类型:

const updateValue = <T1, K1 extends keyof T1, T2>(
  a: T1,
  aKey: K1,
  b: T2,
  bKey: AssignableKey<T2, T1[K1]>
) => {
  a[aKey] = b[bKey];
};

这样修改后:

  • 合法调用时,T1[K1]为number,AssignableKey<typeof b, number>返回'c',参数类型匹配,调用正常。
  • 非法调用时,T1[K1]为string,AssignableKey<typeof b, string>仅返回'd',传入的'c'不在范围内,TypeScript会直接在调用处报错。

方法二:直接在泛型中添加类型约束

也可以不单独定义工具类型,直接在泛型参数中约束类型兼容性:

const updateValue = <T1, K1 extends keyof T1, T2, K2 extends keyof T2>(
  a: T1,
  aKey: K1,
  b: T2,
  bKey: K2 extends (T2[K2] extends T1[K1] ? K2 : never) ? K2 : never
) => {
  a[aKey] = b[bKey] as T1[K1];
};

这种写法同样能实现校验:当T2[K2]无法赋值给T1[K1]时,bKey的类型会被约束为never,调用时直接触发类型错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 21:54:24