Mohsen
Mohsen

Reputation: 65785

How to use an instance with type of union of interfaces in TypeScript?

Consider following TypeScript code:

class A {public name: string = 'A';}
interface B {num: number;}

class Foo {
    get mixed(): Array<A | B> {
        const result = [];
        for (var i = 0; i < 100; i ++) {
            result.push(Math.random() > 0.5 ? new A() : {num: 42});
        }
        return result;
    }

    print(): string {
        return this.mixed.map(item => {
            if (item instanceof A) {
                return item.name;
            }

            return item.num;    
        }).join('\n');
    }
}

Inside the print function, I need to return different values based on type of the item. For type A, it's easy to use instanceof, but for B I can't use instanceof because B is an interface.

TypeScript does not understand that in the line that it says item.num, item is type B for sure and there is no need to complain.

Upvotes: 0

Views: 249

Answers (2)

Sami
Sami

Reputation: 4006

In addition, another way can be to use user defined type guard functions

So, you can have something like

  class A ...
  interface B ...
  function isB(item: any): item is B {
      return item && 'num' in item;
  }

  class Foo {...
     print(): string {
         return this.mixed.map(item => {
            if (item instanceof A) {
              return item.name;
            } else if(isB(item)){
              return item.num;
            }  
    }).join('\n');
  }..

Upvotes: 1

MartyIX
MartyIX

Reputation: 28648

You can use

return (<B>item).num;

to give a hint to the TypeScript compiler.

Upvotes: 1

Related Questions