Type Checking an Interface with Custom User-Defined Type Guard
Explore how to implement custom user-defined type guards in TypeScript to check interface structures without altering types. Learn to use the in operator for property checks and understand how these methods help TypeScript narrow union types, enhancing code reliability and type safety.
We'll cover the following...
User-defined function
A custom user-defined type guard is a function that checks specific parts of the structure of an object to determine if it is one type or another. The advantage is that the type does not need to be altered with a branded property or used with a discriminator. However, it comes with the cost of foregoing functions that check every type.
The following code has a function on line 21 which takes a single parameter of type any. The function checks for two members and because any is used, it can be anything. When the function returns true, the function will help TypeScript to narrow the type to the one defined after is. On line 21, the function narrows to Person.
If the comparison is done in a union with exactly two different types, then the else statement is enough to allow TypeScript to narrow down to the alternative. In the following example, the closure of the if on line 26 narrows the type to Person when the function isPerson returns true. The else will narrow to Animal.
User-defined function with the in keyword
An alternative to checking the property with undefined is using the in operator which will return true if present. The following code has a function isPerson. This time, the function uses in on line 22 to verify if a member exists.
While having a function is a clean way to handle type, it is possible to skip straight to user-defined type guard functions and use in directly, which TypeScript will then narrow. The following code narrows properly when a union is on line 23 as Person and in the else, on line 25, an Animal.
The problem with using in is that as objects get more complex, many comparisons of many properties are often necessary, causing the if statement to grow and repeated along with the codebase. It is not recommended as a pattern to sprinkle conditional code, but it is supported by TypeScript.