2
votes

I'm using Typescript 3.2.2 and unable to achieve the most basic implementation of type guards:

interface Bird {
    fly(): boolean;
}

interface Fish {
    swim(): boolean;
}

function swimIfYouCan(x: Fish | Bird) {
    if ((<Fish>x).swim) {
        return true
    }
}

This produces Error:(50, 11) TS2693: 'Fish' only refers to a type, but is being used as a value here. in WebStorm and SyntaxError: /Users/sea-kent/git/docket-management/webapp/src/App.tsx: Unexpected token (51:8) from yarn. Is there a configuration needed to enable this syntax?

2

2 Answers

1
votes

The recommended way to do pattern matching by checking the existence of a property is the in operator:

interface Bird {
    fly(): boolean;
}

interface Fish {
    swim(): boolean;
}

function move(x: Fish | Bird) {
  if ("swim" in x) {
    return x.swim();
  } else {
    return x.fly();
  }
}

By using the in operator you can avoid the assertion.

1
votes

There are three different approaches possible that come to my mind for your problem.

  1. If you want to cast it and directly use it you have to use the as operator (as mentioned by @jonrsharpe in the comments), so for example (x as Fish).swim

  2. use the in operator to check if it is available, e.g. if ('swim' in x)

  3. Last but not least (and for this case in my opinion the best case), simply do an instance of check to check what instance you've got: if (x instance of Fish)

Edit: Didn't read the question well enough, you can't check for interfaces in runtime. But there is no harm in creating a class on top of the interface