2021-10-09
|~2 min read
|395 words
I’ve written about type guards a few times before - here and here - but I thought I’d collect a few different ways I’ve found to use type guards.
It’s worth remembering why we want to use type guards. They’re useful for type narrowing. We’re looking for strategies to help the compiler know what kind of type we’re working with.
The most common approaches I’ve found split along the line of how the types are joined:
type
” propertytype
propertyWhen we’re trying to narrow a union type where the subtypes share a common property, e.g., type
(e.g., an enum or string literal type).
Let’s think of a fairly simple employee architecture where we store different information for standard employees from administrators.
enum Role {
Standard = "Standard",
Admin = "Admin",
}
type Standard = {
role: Role.Standard
name: string
age: number
}
type Admin = {
role: Role.Admin
name: string
securityLevel: "Normal" | "Elevated" | "High"
}
type Employee = Admin | Standard
Now, if I have a function that takes an Employee
, before I can access certain attributes (age
and securityLevel
), I need to narrow to Standard
and Admin
respectively.
Because we have enriched our employee subtypes to include a role, we just need to look at that to see what kind of employee we’re dealing with.
A type guard works perfectly for that:
function isAdmin(employee: Employee): employee is Admin {
return employee.role === Role.Admin
}
Type
keyWhat about the situation where the types aren’t included as a convenience?
type Standard = {
name: string
age: number
}
type Admin = {
name: string
securityLevel: "Normal" | "Elevated" | "High"
}
type Employee = Admin | Standard
Well, now we need to key off the unique attributes. But, we can’t just inspect them or Typescript will complain.
We still need to narrow, but using the in
keyword, we can do this:
function isAdmin(employee: Employee): employee is Admin {
return "securityLevel" in employee
}
This works because securityLevel
is a unique attribute of the Admin
employee. If it’s present, isAdmin
returns true. If it’s absent, the function returns false
.
These are just a few different ways to narrow our types using type guards (by defining a type predicate).
Hi there and thanks for reading! My name's Stephen. I live in Chicago with my wife, Kate, and dog, Finn. Want more? See about and get in touch!