Home > other >  How to solve error "Type 'string' is not assignable to type 'number'"
How to solve error "Type 'string' is not assignable to type 'number'"

Time:09-22

I recently started to learn to use Angular 14, but I have a problem. I want to use the property "total" that was created in a component, but got that error "Type 'string' is not assignable to type 'number'".

The app.component.html code is:

<div>
  <app-header></app-header>
  <app-total mensaje="Total por pagar: " total="5000"></app-total>
  <app-items></app-items>
</div>

While the component having the "total" property, total.component.ts is:

import { Component, Input, OnInit } from '@angular/core';

@Component({
  selector: 'app-total',
  templateUrl: './total.component.html',
  styleUrls: ['./total.component.css']
})
export class TotalComponent implements OnInit {

  @Input() total:number = 0;
  @Input() mensaje:string = '';

  constructor() { }

  ngOnInit(): void {
  }
}

CodePudding user response:

<div>
  <app-header></app-header>
  <app-total mensaje="Total por pagar: "  [total]="5000"></app-total>
  <app-items></app-items>
</div>

CodePudding user response:

You need to use property binding syntax for the value to be evaluated as a number:

<app-total mensaje="Total por pagar: " [total]="5000"></app-total>

CodePudding user response:

To pass a number directly as a number @Input to the component, or a true/false as a boolean @Input, or even an array, without using Angular's Property binding, we can take advantage of functions and types of Angular's CDK Coercion (or create our own if we don't want to depend on @angular/cdk).

For example, to pass a number @Input to the component, we can do the following:

import { coerceNumberProperty, NumberInput } from '@angular/cdk/coercion';

@Input()
get total() { return this._total; }
set total(value: NumberInput) {
  // `coerceNumberProperty` turns any value coming in from the view into a number, allowing the
  // consumer to use a shorthand string while storing the parsed number in memory. E.g. the consumer can write:
  // `<app-total total="500"></app-total>` instead of `<app-total [total]="500"></app-total>`.
  // The second parameter specifies a fallback value to be used if the value can't be parsed to a number.
  this._total = coerceNumberProperty(value, 0);
}
private _total = 0;

Which allows the consumer to use a shorthand string while storing the parsed number in memory as follows:

<app-total mensaje="Total por pagar: " total="5000"></app-total>

If we don't want to use the CDK's built-in functions and types, we can take a look at their definition in the Angular Components repo under components/src/cdk/coercion folder.

For example, we have to define the following type and functions to handle the number property:

/**
 * Type describing the allowed values for a number input
 */
export type NumberInput = string | number | null | undefined;

/** Coerces a data-bound value (typically a string) to a number. */
export function coerceNumberProperty(value: any): number;
export function coerceNumberProperty<D>(value: any, fallback: D): number | D;
export function coerceNumberProperty(value: any, fallbackValue = 0) {
  return _isNumberValue(value) ? Number(value) : fallbackValue;
}

/**
 * Whether the provided value is considered a number.
 */
export function _isNumberValue(value: any): boolean {
  // parseFloat(value) handles most of the cases we're interested in (it treats null, empty string,
  // and other non-number values as NaN, where Number just uses 0) but it considers the string
  // '123hello' to be a valid number. Therefore we also check if Number(value) is NaN.
  return !isNaN(parseFloat(value as any)) && !isNaN(Number(value));
}

And the same for the functions and types of the boolean-property, string-array, and array.

  • Related