1

I'm trying to call a service function in Angular 9 from input in a text field to convert Celsius to Kelvin. I specified one function that takes in the degrees in Celsius, in order to compute to Kelvin by adding 273.15. Instead, it concatenates on the front end instead. I tested the code and sure enough it returns string, after just accepting it as number. Casting as a number resolves the issue, but can anyone help me understand why typing didn't fail the call or at the least cast it on the fly?

    public convertCToK(celsius: number): number { // e.g. celsius = 1
        console.log(typeof celsius); // returns 'string'
        // return celsius + 273.15; returns 1273.15
        return Number(celsius) + 273.15; // returns 274.15
    }

The calling function and HTML

    fahrenheit: number;
    celsius: number;
    kelvin: number;

    changeC() {
      if (!isNaN(this.celsius)) {
        this.fahrenheit = Math.round(this.calcService.convertCToF(this.celsius) * 100) / 100;
        this.kelvin = Math.round(this.calcService.convertCToK(this.celsius) * 100) / 100;
      }
    }
    <h2>Fahrenheit:
      <label>
        <input style="color:green" type='text' [(ngModel)]='fahrenheit' (keyup)="changeF()">
      </label>
    </h2>
    <hr>
    <h2>Celsius:
      <label>
        <input style='color:blue' type='text' [(ngModel)]="celsius" (keyup)="changeC()">
      </label>
    </h2>
    <hr>
    <h2>Kelvin:
      <label>
        <input style="color:red" type='text' [(ngModel)]='kelvin' (keyup)="changeK()">
      </label>
    </h2>
Kurt Hamilton
  • 12,490
  • 1
  • 24
  • 40
UnkJester
  • 13
  • 3

2 Answers2

1

Binding a text input to a property will always result in that property being set as a string when it is updated. Declaring it as a number type has no impact on the runtime value, Typescript just assists you at design time.

If you want to treat the property bound to an input as a number, then you should set the input type as number.

<input style='color:blue' type='number' [(ngModel)]="celsius" (keyup)="changeC()">

DEMO: https://stackblitz.com/edit/angular-dskyke

Notice how in my demo the properties bound to text inputs start out as numbers. When they are updated, they become strings.

Kurt Hamilton
  • 12,490
  • 1
  • 24
  • 40
  • Got ya. I was confused that because the value ended up a string, it still allowed a call to function(number) even though it was a string.Thanks for the demo! Wish I could accept both answers – UnkJester May 01 '20 at 21:51
1

Since your <input> is defined as type="text", the input will be a string (even if you type a number).

The isNaN(someString) function will return false if someString you pass into the method also can be read as a number, e.g. "123". see some examples from w3school

Since this is a runtime issue (because you define celsius: number; in your typescript file, but the html does indeed provide you with a string), you will not get "compile errors". Changing the type="number" in your input will solve the issue you are facing, but will also provide you with a different UI for your input.

When you try to take a sum of a string + number (even though the string is "10" or some other number-like string), you may get unexpected results.

Side note

typing Number(celsius) is not the same as casting. You are converting the string to a number. If you wanted to cast it, you would write <Number> celsius Relevant answer to casting here

John
  • 10,165
  • 5
  • 55
  • 71
  • Interesting, okay so as a follow up question: the method call convertCToK(celsius) passes because in the main class the celsius variable is designated as a number, correct? I'm used to Java strong typing, but I suppose it makes sense that if the javascript changes to string, it would still allow the method call. – UnkJester May 01 '20 at 21:49
  • Yes, you are right. Typescript is strongly typed as well, but in the end it boils down to javascript. The error you are facing is because of the relation between html and typescript. Typescript does not care about what the input type is – John May 01 '20 at 23:31