19

The typescript handbook on user defined type guards defines an example type guard as

function isFish(pet: Fish | Bird): pet is Fish {
    return (<Fish>pet).swim !== undefined;
}

Is there a corresponding syntax for arrow functions?

LudvigH
  • 3,662
  • 5
  • 31
  • 49

5 Answers5

26

TypeScript supports arrow-function type guards (which may have not been the case in 2017). The following now works as expected. I've used this style frequently in production code:

const isFish = (pet: Fish | Bird): pet is Fish => 
  (pet as Fish).swim !== undefined;
James Dunne
  • 680
  • 6
  • 9
5

Use type assertion instead of type declaration:

const isFish = (pet => !!pet.swim) as (pet) => pet is Fish 

However, given the fact that it is more verbose, I would prefer to write type guards as normal functions, unless you really need the this binding, but that is probably a code smell.

unional
  • 14,651
  • 5
  • 32
  • 56
3

Yes, just as you would have returned boolean, you simply return pet is Fish:

const isFish: (pet: Fish | Bird) => pet is Fish = pet => (pet as Fish).swim !== undefined

Arrow functions are declared as a single type ((pet: Fish | Bird) => pet is Fish) rather than the parameters and the return type separately.

Madara's Ghost
  • 172,118
  • 50
  • 264
  • 308
  • How do I combine the declaration and implementation for arrow functions then? (to make it comparable to the syntax example in the handbook?) – LudvigH Dec 16 '17 at 15:23
  • This gives a compiler error. C.f. this [playground snippet](https://www.typescriptlang.org/play/#src=interface%20Bird%20%7B%0D%0A%20%20%20%20fly()%3B%0D%0A%20%20%20%20layEggs()%3B%0D%0A%7D%0D%0A%0D%0Ainterface%20Fish%20%7B%0D%0A%20%20%20%20swim()%3B%0D%0A%20%20%20%20layEggs()%3B%0D%0A%7D%0D%0A%0D%0Aconst%20isFish%3A%20(pet%3A%20Fish%20%7C%20Bird)%20%3D%3E%20pet%20is%20Fish%20%3D%20pet%20%3D%3E%20(pet%20as%20Fish).swim%20!%3D%3D%20undefined%0D%0A) – LudvigH Dec 16 '17 at 15:28
2

as an alternative, this also works

const isFish = (pet: any): pet is Fish => !!pet.swim;

or if you prefer to be more explicit

const isFish = (pet: any): pet is Fish => typeof pet.swim === 'function';

while the test can be made against properties as well

const isFish = (pet: any): pet is Fish => pet.hasOwnProperty('genus');
Community
  • 1
  • 1
Dan Dohotaru
  • 2,809
  • 19
  • 15
-1

This works for me:

const importList = children.filter(
  (node): node is MeshFullType<Mesh.Import> =>
    code.isMeshFullType(node, Mesh.Import),
)
Lance
  • 75,200
  • 93
  • 289
  • 503