Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I check a type against a union type in typescript?

Tags:

Is there a way to do an "instanceof"-like query on an object against a union type that's built into the language?

I have a type alias with a union type as follows:

type MyType = Foo | Bar | Thing;

Each of Foo, Bar and Thing inherit from Base

class Base { /* ... */ }
class Foo extends Base { /* ... */ }
class Bar extends Base { /* ... */ }
class Thing extends Base { /* ... */ }

Some method returns a Base.

function getBase(): Base { /* ... */ return base; }

Ideally, I would like to create another method that can return a MyType after calling getBase()

function getMyType(): MyType { 
    var item = getBase();
    if (item instanceof MyType)
        return item;
    else
        return null;
}

If MyType were not a type alias, the above code would work. However, since it is a type alias, it doesn't seem to work. So to re-iterate my question, is something of this nature built into the language?

Clearly, what I want can be accomplished by checking the instanceof query against each individual class:

function getMyType(): MyType { 
    var item = getBase();
    if (item instanceof Foo || item instanceof Bar || item instanceof Thing)
        return item;
    else
        return null;
}

But this is hardly ideal; if some future developer wanted to create OtherThing and extend MyType to also include this new class, then hopefully remembered to update getMyType().

Is there a feature built into the language to address this, or is there potentially a better way of doing this?

like image 413
mejdev Avatar asked Oct 27 '15 21:10

mejdev


2 Answers

There's no runtime representation of type aliases, so there's nothing "built in" per se for doing this kind of check.

This pattern would be fairly maintainable, though:

// Future devs: Please keep these in sync
type MyType       =  Foo|Bar|Thing;
let MyTypeClasses = [Foo,Bar,Thing];

function getMyType(): MyType { 
    var item = getBase();
    if (MyTypeClasses.some(c => item instanceof c))
        return item;
    else
        return null;
}
like image 154
Ryan Cavanaugh Avatar answered Oct 05 '22 10:10

Ryan Cavanaugh


If you knew some specific key for an interested Type you can do it via in operator:

function move(pet: Fish | Bird) {
  if ("swim" in pet) {
    return pet.swim(); //pet is Fish
  }
  return pet.fly(); //pet is Bird
}

As for me much easier than an additional function with stuff. That what I was looking for.

Docs.

like image 36
Experimenter Avatar answered Oct 05 '22 09:10

Experimenter