Received a string instead of a number in a Typescript function parameter declaration

I'm attempting to utilize a service function in Angular 9 that converts Celsius to Kelvin based on user input from a text field. I have defined a function that takes the Celsius degrees as input and computes the equivalent Kelvin by adding 273.15. However, instead of performing the calculation correctly, it seems to concatenate the values on the front end. Upon testing the code, I discovered that it returns a string even though I expected it to be a number. By explicitly casting the input as a number, I was able to resolve the issue. Can someone provide insight into why the input type did not cause the call to fail or at least perform a dynamic cast?

    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 following snippet shows 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>

Answer №1

When your input field is set as type="text", any value entered will be treated as a string, even if it appears to be a number.

If you use the isNaN(someString) function and pass in a value that can be read as a number (e.g., "123"), it will return false. You can find examples of this behavior on W3Schools.

This issue arises at runtime because you have defined celsius: number; in your TypeScript file while receiving a string from the HTML input. Therefore, you won't encounter compile errors. Changing the input type to number will resolve the problem but may alter the appearance of the UI.

Adding a string to a number (such as a number-like string like "10") may lead to unexpected outcomes.

Note

Using Number(celsius) performs a conversion from string to number, not casting. To cast the variable, you would utilize <Number> celsius. Refer to this Stack Overflow answer on casting for more information.

Answer №2

When you bind a text input to a property, the property will always be treated as a string when it gets updated. Even if you declare it as a number type, it doesn't affect the actual runtime value - Typescript just helps with design time.

If you want the property bound to an input to be treated as a number, make sure to set the input type as number like this:

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

Check out this DEMO for a practical example: https://stackblitz.com/edit/angular-dskyke

In the demo, you'll see that even though the properties are initially numbers when bound to text inputs, they end up being stored as strings after updating.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using Typescript inject with Vue 3 is currently not functioning as expected. The issue arises when trying to create spread types from object types

When using Vue 3 and TypeScript, an error is encountered (as shown below) only when the script lang="ts" attribute is present. Can someone provide insight into why the inject function in Vue 3 with TypeScript does not function correctly? ERROR in src/compo ...

Unable to perform action on Angular 4 data table page. The NGX Store and effect are not functioning properly

Every time I click on the "go to page" button, it redirects me back to page 1. I recently switched to Angular 4, which is quite new to me since I started with Angular 1 a while ago. The strange thing is that the console.log in the page component is loggin ...

Issues with Angular 9 routerLinkActive functionality causing unexpected behavior

Whenever I navigate to a different router link, the previous link remains active, resulting in multiple active links with the same class. <div class="side-link" [routerLink]="['/']" [routerLinkActive] = "['link-active']">Dashboar ...

Angular 5 - Empty array containing objects has a length of zero

In my app.component.ts file, I have an array initialized to load objects in the onInit event: ngOnInit() { this.pages = []; } Within the ngOnInit event, I also have a setInterval method that evaluates an expression every few milliseconds: setInterval(() ...

Using Math.min() or Math.max() syntax in Angular templates: A comprehensive guide

Within my pagination module, the following code snippet can be found: <p>Displaying {{(page-1) * pageSize}} to {{ Math.min((page-1) * pageSize + pageSize,tasks.length)}} out of {{tasks.length}}</p>. Unfortunately, it seems to be experiencing ...

Angular2 - Retrieve data in XLS format from RestService并下载

I am looking to create a web service using Apache POI to generate an Excel file (xls, xlsx). Below is the snippet of code I have put together: @RequestMapping(value = "/export", method = RequestMethod.GET) public void exportXlsx(HttpServletResponse respon ...

How can I avoid a component from triggering its subscription twice in Angular 5 when the component is nested twice inside another component?

How can I prevent a component in Angular 5 from triggering its subscription twice when the component is placed twice inside another component? For example, I have a NavMenuComponent with two instances of a cart in its template. <!-- cart 1 in n ...

Using Multiple Router Outlets in Angular 4

<div *ngIf="!loggedIn" class="login"> <router-outlet></router-outlet> </div> <div *ngIf="loggedIn" class="main"> <router-outlet></router-outlet> </div> Containing within this code snippet are a login co ...

Utilizing ngClassEven and ngClassOdd in Angular 2 for Improved Styling

I attempted to replicate the behavior of ng-class-even and ng-class-odd (originally from Angular 1) in my Angular 2 application. Below is the code I wrote and it's functioning correctly, but I'm curious if there are alternative methods to achiev ...

An uncommon token was found by Jest - import (Angular CLI 6)

Struggling to get jest installed and running in an angular/cli (v6) app on Mac. Despite trying various methods to set up jest, I keep encountering the following error: Test suite failed to run Jest encountered an unexpected token This usually me ...

Using TypeScript to pass parameter in a chained function

When using node.js, I am calling a script with `exec` from the `child_process` module. In the closed state, I need to verify if there was any error so that I can handle it properly. However, I am facing an issue where I cannot access the `error` parameter ...

Is it possible to create a class object with properties directly from the constructor, without needing to cast a custom constructor signature

class __Constants__ { [key: string]: string; constructor(values: string[]) { values.forEach((key) => { this[key] = key; }); } } const Constants = __Constants__ as { new <T extends readonly string[]>(values: T): { [k in T[num ...

What is the process for changing the name of an element in Angular 2?

I'm feeling a bit lost here ... I need to implement the feature that allows users to edit the name of an element by simply clicking on a button. These elements are all stored in the Storage system. How can I achieve this in my current setup? File: ho ...

Angular - Dismiss modal triggered by service, from a header module

Within my Angular application, I have Service S that is responsible for opening Component C MatDialog; I am aiming for C to include a reusable header component called Component H; My goal is for H to feature a button that can close the MatDialog within C; ...

Issues with Cloud9 Angular and NodeJS connecting to API on a separate port of the same server

I am currently utilizing an AWS Cloud9 IDE for my project. Angular is running on port 8080, while my NodeJS (with Express) server is running on port 8081. In my Node app.js file, I have set up CORS headers as follows: const app = express(); app.use(expre ...

Verifying the length of arrays with Typescript index typing

Could someone please clarify why y.length in this particular example does not result in an error? Click here to view the playground ...

Instructions for removing a specific row from a table by clicking on the icon or button

Currently in my project, I am utilizing the Table with pagination component. My goal is to implement a feature where users can delete a single row at a time by clicking on the delete icon. To showcase what I have tried so far, I have set up a demonstration ...

Encountered an issue with Angular Material sidenav: The synthetic listener @transform.start was found

Click here to visit the StackBlitz link Encountering an issue while attempting to utilize the material side nav. Error message: preview-29b0f46fcc27b310236ab.js:1 ERROR Error: Uncaught (in promise): Error: Found the synthetic listener @transform.start. P ...

Angular component template fails to recognize data that is clearly defined and present within the component

Here is a snippet of code from my component: import { Component, OnInit } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Component({ selector: 'app-home', templateUrl: './home.component. ...

Sharing data between two Angular 2 component TypeScript files

I'm facing a scenario where I have two components that are not directly related as parent and child, but I need to transfer a value from component A to component B. For example: In src/abc/cde/uij/componentA.ts, there is a variable CustomerId = "sss ...