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

如何用TypeScript编写修改对象指定数值类型属性的函数?

解决TypeScript中泛型函数修改数字属性的类型约束问题

需求是实现一个double函数,接收对象和属性名,将该属性的值翻倍。JavaScript实现十分直接,但TypeScript的泛型类型检查会带来约束问题,以下是可行的解决办法:

报错原因梳理

  • 第一种写法报错:keyof T对应的属性类型不明确,TypeScript无法确认它属于可执行算术操作的类型(number/bigint等),因此阻止操作。
  • 第二种写法报错:T[K]可能是number的子类型(比如字面量类型5),直接赋值普通number类型会触发子类型不兼容的错误。

可行解决方案

方案1:类型断言快速实现

直接用类型断言告知TypeScript目标属性为number类型,绕过类型检查:

function double<T>(object: T, property: keyof T) {
  (object[property] as number) *= 2;
}

特点:写法简洁,但如果传入非数字属性会导致运行时错误,适合能保证调用参数合法的场景。

方案2:运行时类型检查+类型断言

先通过运行时检查确认属性为数字,再用断言解决子类型兼容问题:

function double<T, K extends keyof T>(object: T, property: K): void {
  const value = object[property];
  if (typeof value === 'number') {
    object[property] = value * 2 as T[K];
  }
}

特点:增加运行时校验,安全性更高;用as T[K]确保赋值结果符合原类型约束,解决字面量子类型的兼容问题。

方案3:严格约束对象属性类型

直接限制传入对象的目标属性必须为number类型:

function double<K extends keyof any>(object: { [P in K]: number }, property: K) {
  object[property] *= 2;
}

也可以用Record简化写法:

function double<K extends string>(object: Record<K, number>, property: K) {
  object[property] *= 2;
}

特点:编译期就会阻止非数字属性的传入,彻底避免运行时错误;对象包含其他非数字属性时,只要目标属性符合要求即可正常使用。

方案4:利用asserts增强类型推断(TS 3.7+)

通过asserts语法让TypeScript知晓,调用函数后目标属性的类型为number,提升后续代码的类型推断能力:

function double<T, K extends keyof T>(object: T, property: K): asserts object is T & { [P in K]: number } {
  (object[property] as number) *= 2;
}

特点:调用函数后,TypeScript会自动将目标属性的类型推断为number,后续代码无需重复做类型检查;同样需要保证传入的属性确实是数字类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 00:53:27