-1

I am trying to subtract two numbers but I get The right-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.:

const ls = Object.values(localScore)[0];
const s = Object.values(score)[0];
console.log(typeof ls); // number
console.log(typeof s); // number
const diff = s - ls;
              // ^ The right-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.

What I am doing wrong? I am using TypeScript.

pilchard
  • 12,414
  • 5
  • 11
  • 23
John Doener
  • 119
  • 10
  • 1
    What are the type definitions on `localScore` and `score`? – Nicholas Tower Dec 18 '21 at 15:48
  • @NicholasTower does it really matter? He already said that the two variables are a number type – Essay97 Dec 18 '21 at 15:50
  • 1
    @Essay97 it matters because the *runtime type* is not what *TypeScript uses at compile time*. – VLAZ Dec 18 '21 at 15:50
  • @Essay97 Yes, because evidently typescript is unaware that `ls` and `s` are numbers. And since there are no types in the code shown, typescript must be deducing the types from `localScore` and `score`. – Nicholas Tower Dec 18 '21 at 15:51
  • Adding type definition to `localScore` and `score` solves the issue. I had the same assumption as Essay97. Ty – John Doener Dec 18 '21 at 15:56
  • @JohnDoener Even though [you said](https://stackoverflow.com/questions/70404814/how-to-subtract-wo-numbers-in-typescript#comment124454130_70404814) that you solved your compiler problem... while [object keys are deterministically-ordered](https://stackoverflow.com/a/5525820/438273) in some runtime environments, it's still not safe to perform operations on values held in two separate objects, accessing them by a correlated numeric index. – jsejcksn Dec 18 '21 at 16:04
  • @jsejcksn I don't get that point. Can you add this as an answer? Sample Data: `localScore = {foo: 10}` `score = {foo: 15}` (side note: I don't know that foo is foo) – John Doener Dec 18 '21 at 16:14
  • @JohnDoener Sure: composing now. – jsejcksn Dec 18 '21 at 17:59

1 Answers1

0

While object keys are deterministically-ordered in some runtime environments, it's still not safe to perform operations on values held in two separate objects, accessing them by a correlated numeric index.

According to the information in your comment, it sounds like you don't know the name of the property holding the value that you want to target in each object, but you do know that the name is the same in both objects, so a safer approach would be:

TS Playground

/** Given that values in the objects are correlated by property key: */
function getDiff <
  K extends PropertyKey,
  T extends Record<K, number>,
>(minuend: T, subtrahend: T, key: K): number {
  return minuend[key] - subtrahend[key];
}

type NumberValues = Record<string, number>;
declare const localScore: NumberValues;
declare const score: NumberValues;

const [key] = Object.keys(localScore); // destructure first enumerable property key
const diff = getDiff(score, localScore, key); // number, but possibly negative
const absoluteDiff = Math.abs(diff);
jsejcksn
  • 27,667
  • 4
  • 38
  • 62