TypeScript Type Guards
A type guard is a function that checks a value and returns a type predicate. The predicate names the type the value has when the check passes.
A guard for string
isText returns a predicate for string. The true branch can call string methods on the value.
function isText(value: string | number): value is string {
return typeof value === "string";
}
function show(value: string | number): void {
if (isText(value)) {
console.log(value.toUpperCase());
} else {
console.log(value.toFixed(1));
}
}
show("hello");
show(42);A guard in a loop
The guard tests each item in the array. Only the strings pass and get logged.
function isText(value: string | number): value is string {
return typeof value === "string";
}
const values: (string | number)[] = ["a", 1, "b", 2, "c"];
for (const value of values) {
if (isText(value)) {
console.log(value.toUpperCase());
}
}Example
interface Admin {
role: "admin";
name: string;
}
interface Guest {
role: "guest";
name: string;
}
function isAdmin(person: Admin | Guest): person is Admin {
return person.role === "admin";
}
function greet(person: Admin | Guest): void {
if (isAdmin(person)) {
console.log("Admin " + person.name);
} else {
console.log("Guest " + person.name);
}
}
greet({ role: "admin", name: "Ana" });
greet({ role: "guest", name: "Ben" });Key points
- A type predicate is written with is after the parameter name.
- The guard returns true when the value has the named type.
- A passing guard narrows the value inside the branch.
- The compiler trusts the predicate the guard declares.
- A guard can test a value with typeof or with a property check.
In this example, isAdmin checks the role field of each person. A true result narrows the person to Admin in the branch. The two calls log one line for an admin and one line for a guest.
Note
A wrong guard misleads the compiler. The runtime value does not change.
Try it Yourself
Edit the code, then press Run.
Running is simulated ยท TypeScript Playground
Exercise
What does a type predicate in a guard return type declare?