type guard
is a function that takes a type and returns a boolean. TypeScript uses it to determine if the element type can be narrowed down.
It's needed when we try to filter our data and end up returning a narrowed type. In the following case, we want filter to filter the array to only include elements that aren't a string.
interface User {
email: string;
userId: number;
name: string;
}
const users = ['hi', 'hello', { email: 'wrong', userId: 1, name: 'mike' }]
const selectedPeople: (string | User)[] = [...users];
// Type guard that narrow down x type to User if the condition is true
const isUser = (x: string | User): x is User => typeof x !== "string"
/*
Type '(string | User)[]' is not assignable to type 'User[]'.
Type 'string | User' is not assignable to type 'User'.
Type 'string' is not assignable to type 'User'.
*/
const existingUsers: User[] = selectedPeople.filter((people) => typeof people !== "string");
It throws an error because it doesn't now that we're trying to narrow the type down to a User.
We solve it with a type guard!
interface User {
email: string;
userId: number;
name: string;
}
const users = ['hi', 'hello', { email: 'wrong', userId: 1, name: 'mike' }]
const selectedPeople: (string | User)[] = [...users];
// Type guard that narrow down x type to User if the condition is true
const isUser = (x: string | User): x is User => typeof x !== "string"
// No error
const existingUsers: User[] = selectedPeople.filter(isUser);
existingUsers // [ { email: 'wrong', userId: 1, name: 'mike' } ]