运营商' +'不能应用于类型'数字'和' T [K]'

时间:2018-03-29 19:38:48

标签: typescript

我有这个代码块:

function sumOnValue<T, K extends keyof T>(collection: Array<T>, key: K): number {
  let result = 0;
  for (const o of collection) {
    const sample = o[key];
    if (typeof o[key] === 'number') {
      result = result + sample; // [ts] Operator '+' cannot be applied to types 'number' and 'T[K]'.  red squigly line under sample.
    }
  }
  return result;
}

const sampleCharges: Array<ICharge> = [
  {
    AllowedAmount: 10,
  },
  {
    AllowedAmount: 15,
  },
  {
    AllowedAmount: 9,
  },
];

const resultedSum = sumOnValue(sampleCharges, 'AllowedAmount');
console.log(resultedSum);

如上所述,我从编译器中得到错误(vscode报告它是一个问题)但是在运行代码时它很好并且没有抱怨。我应该在这里做什么来抑制错误或通过类型检查安全地编写这种方法&#39;?

简而言之,目标是:T数组中添加给定属性,前提是给定属性是T中的类型且属性为一个数字。

2 个答案:

答案 0 :(得分:1)

您可以使用type guard执行此操作 - 实现执行相同isNumber检查的函数typeof

function isNumber(x): x is number {
    return typeof x === "number";
}

function sumOnValue<T, K extends keyof T>(collection: Array<T>, key: K): number {
  let result = 0;
  for (const o of collection) {
    const sample = o[key];
    // use here
    if (isNumber(sample)) {
      result = result + sample;
    }
  }
  return result;
}

答案 1 :(得分:0)

在TypeScript 2.1+中,可以使用索引访问类型来完成。与类型保护不同,索引访问类型是编译时检查,永远不会进入JavaScript。

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html

function pickAndReduce<T>(
    collection: Array<{ [k in keyof T]: number }>,
    key: keyof T
): number
{
    let result = 0;
    for (const o of collection) {
        result = result + o[key];
    }
    return result;
}

如果需要,可以减少循环。

function pickAndReduce<T>(
    collection: Array<{ [k in keyof T]: number }>,
    key: keyof T
): number
{
    return collection.reduce((total, item) => total + item[key], 0);
}

编辑:

最初我有key: string,如示例所示,但正如评论中所指出的,这忽略了对索引访问的类型检查。我已将其更改为key: Key of T,因此只能使用给定对象上的键调用该函数。