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

TypeScript如何约束泛型对象指定键取值类型为数值以支持减法运算

核心问题说明

你原有的类型约束逻辑错误,keyof T & number 是约束键名本身为数字类型,而非你需要的「键对应的属性值为数字类型」,同时泛型T没有对应约束,所以TS无法识别value[key]是number类型,自然不允许执行减法操作。
另外原代码中array.map()的写法无效,map不会修改原数组,会返回新数组,你没有接收返回值的情况下执行完原数组不会有任何变化。


解决方法

调整泛型约束,用双泛型明确限定传入的key对应的属性值必须为number,以下提供两种常用实现:

1. 不修改原数组/原对象,返回新的差分结果数组(推荐)

function ForwardTimePointDifferenceTransformer<T extends Record<K, number>, K extends keyof T>(
  array: T[],
  key: K
): T[] {
  return array.map((item, index, arr) => {
    // 最后一个元素没有下一个取值,保留原值
    if (index === arr.length - 1) {
      return { ...item };
    }
    // 浅拷贝避免修改原对象
    return {
      ...item,
      [key]: arr[index + 1][key] - item[key]
    };
  });
}

2. 直接修改原数组/原对象

function ForwardTimePointDifferenceTransformer<T extends Record<K, number>, K extends keyof T>(
  array: T[],
  key: K
): T[] {
  array.forEach((item, index, arr) => {
    if (index === arr.length - 1) return;
    item[key] = arr[index + 1][key] - item[key];
  });
  return array;
}

约束说明

  • K extends keyof T:限定K必须是T类型的合法键名
  • T extends Record<K, number>:限定T类型在K键上的取值必须是number类型

使用你提供的示例数组测试,传key: 'numberValue'时类型校验完全通过,如果你误传key: 'value',TS会直接在编译阶段抛出错误,提示该键对应的类型不是number,不符合入参要求。原代码中的非空断言!也不再需要,类型约束已经保证了取值一定是数字。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 12:54:02