Argument of type 'string | number' is not assignable to parameter of type 'number'

25.4k views Asked by At

Question Modified With an example method to the end: -

I have an interface as shown below for typing an object.

export interface IList{
  name: string;
  age: number;
  option: number;
  quantity: number;
  priority: number;
}

Due to some requirement I have to assign a "string" to the "priority" property at the end of all operations before sending it to the backend.

As I've to assign a string, I tried using a union operator :-

priority : number | string; But all the other pieces of code wherever I used other operations taking this as a number into consideration is also throwing me the below error:

Argument of type 'string | number' is not assignable to parameter of type 'number'
  Type 'string' is not assignable to type 'number'.

How do I get around this and use priority as a both a string and number to type my object.

Here is one condition where I am using the "IList" interface as a type and assigning a number if multiGroupHeader is true, else I have to assign a string :-

public updatePriorities(Lists: IList[]) {
  if (!this.multiGroupHeader) {
    const priorities = Lists.map((list: IList) => list.priority);
    const uniquePriorities = [...new Set(priorities)];
    if (uniquePriorities.length === 1 && uniquePriorities[0] === 1) {
      return;
    }
    uniquePriorities.sort((priority1: number, priority2: number) => priority1 - priority2);
    const updatedPriorities = uniquePriorities.map((priority: number, index: number) => {
      return index + 1;
    });

    uniquePriorities.forEach((id: number, index: number) => {
      Lists.forEach((list: IList) => {
        if (list.priority === id) {
          list.priority = updatedPriorities[index];
        }
      });
    });
  } else {
    Lists.forEach((list: IList) => (list.priority = "CURRENT"));
  }
}
2

There are 2 answers

0
night_owl On

One way you can work around this is by asserting/narrowing the type before handing it to the functions that expect only a string or number:

if (typeof list.priority === 'number') {
  // list.priority's type inside these braces is only 'number'
}

There are other ways assert the type of a variable, too: https://www.typescriptlang.org/docs/handbook/basic-types.html#type-assertions

4
Ambroise Rabier On

You can cast to number:

const strOrNumber: string | number = 5;
const iAmSureThisIsANumber: number = strOrNumber as number;

But, if it become a string, only before shipping it to the backend, it would be better to have two IList. Yes it is more code, but this make things more explicit.

export interface IList {
  name: string;
  age: number;
  option: number;
  quantity: number;
  priority: number;
}

export interface IListForServer {
  name: string;
  age: number;
  option: number;
  quantity: number;
  priority: string;
}

With some sugar you can use a utility type.

type IListForServer = Omit<IList, 'priority'> & {priority: string};