添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

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"));
                Sometimes you are using List and sometimes IList as type, does List have the property priority set to the union type as well?
– Carlos
                Mar 6, 2020 at 14:02
                "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." Then the type declaration should allow it to be a string. There is no point having a type declaration if it's a lie!
– kaya3
                Mar 6, 2020 at 14:16
                @kaya3: Either that, or declare another type for returning data to the server, where the priority property is always a string. Beats having to include if (typeof(list.priority) === 'number) {...}' in every single instance where that property is used.
– CGundlach
                Mar 6, 2020 at 14:26
                Sure; the type for one purpose doesn't have to be the same as the type for a different purpose.
– kaya3
                Mar 6, 2020 at 14:38

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

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};
                I tried it this way  Lists.forEach((list:IListForServer ) => list.priority = "CURRENT"). But the issue is the paraemeter to the method is of the type IList[] ( public updatePriorities(Lists: IList[])), so changing something inside to  IListForServer  is throwing me an error. I tried using a Union type : - public updatePriorities(Lists: IList[] | I IListForServer[] ) event this is throwing an error. Error in next comment.
– Veryon890
                Mar 6, 2020 at 15:03
                Type '(list: IList) => void' is not assignable to type '(value: IListForServer, index: number, array: IListForServer[]) => void'.     Types of parameters 'list' and 'value' are incompatible.       Type 'IListForServer' is not assignable to type 'IList'.         Types of property 'priority' are incompatible.           Type 'string' is not assignable to type 'number'.  	       list.forEach((darkPool: IList) => {
– Veryon890
                Mar 6, 2020 at 15:04
                @Veryon890 When you said "before sending it to the backend" I assumed this was an http request, not in the showed code, it seem I was mistaken. I feel like there is some structuring issue. Maybe you can add a field in IList priorityIsCurrent: boolean so that you don't have to do list.priority = "CURRENT".
– Ambroise Rabier
                Mar 6, 2020 at 15:42
                @Ambrose - For now, I separated out the else condition from this method and included it wherever I am calling the function.                                                                                    if (!this.multiGroupHeader) {         this.updatePriorities(this.fetchedList);       } else {         this.fetchedList.forEach(           (list: IListForServer) => (list.priority = 'CURRENT')         );       }
– Veryon890
                Mar 9, 2020 at 3:25
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.