Checking the type of an object in Typescript: the type guards
Coming from a JS background, checking the type of an object in Typescript is kind of obscure at first. We are used to if(obj.property) {//obj.property exists here !}
and this is not possible in Typescript…
In some cases, you can use type guards. You guessed, this is what this article is about :)
TL;DR/Reminder
Type your function with is
:
function typeGuard(toBeDetermined: any): toBeDetermined is Animal {}
or the fat arrow version:
const tg = (tbd: any): tbd is Animal => {//return true if Animal}
Type checking
Our problem is classic in Typescript: an object type is undifferentiated, and we would like to differentiate the different cases. In the example below, we have two interfaces, Animal and Person:
If we want to print the name, it’s easy.
But if we want to print “cat”, “”dog” or “human”, it becomes more complicated… Below, both functions don’t work:
The first one because type is not defined, the second one because instanceof
works with classes. And in our case, both Person and Animal are interfaces, and there is no way instanceof
will work at runtime.
Solution: A type guard
Typescript allows us to create our own function, that it will understand, and will narrow the type in the following code (in terms of scope, of course)
A type guard is some expression that performs a runtime check that guarantees the type in some scope.
(source: http://www.typescriptlang.org/docs/handbook/advanced-types.html)
The key here is the type of this function: toBeDetermined is Animal
. Typescript understands that if we return true
, the argument is an Animal. We can now use this variable:
It works ! Magic, right ?
Warning: a type guard can introduce errors
A type guard has to be correct, otherwise it can introduce errors. Consider the following gist:
The type guard is definitively wrong, and yet, Typescript is OK. But at runtime, undefined
appear. And you see the too classic cannot read property 'alpha' of undefined
coming…
Going further
If you want to learn more about typeguards, the official documentation can be a good starting point, although, as of today, it uses the good old Typescript 2.0’s typecast <>
If you want to write secure type guards, for example validating objects fetched from an API, you can check:
Now you know how to narrow a type of an object :). Hope it helped !