TypeScript Type Predicates
A type predicate is a return type that names the narrowed type of a parameter. It lets one written check narrow values everywhere the check is reused.
Filtering without a predicate keeps the union
The callback is annotated to return a plain boolean. The filtered array keeps the union, and a string method on an element is refused.
const mixed: (string | number)[] = ["pen", 42, "pad", 7];
function keepText(v: string | number): boolean {
return typeof v === "string";
}
const filtered = mixed.filter(keepText);
console.log(filtered[0].toUpperCase());A predicate narrows the filtered array
The return type `v is string` is the predicate. Filter now returns a string array, and string methods work on every element.
function isText(v: string | number): v is string {
return typeof v === "string";
}
const mixed: (string | number)[] = ["pen", 42, "pad", 7];
const words = mixed.filter(isText);
console.log(words.map((w) => w.toUpperCase()).join(", "));
console.log(words.length);A predicate over object shapes
A predicate can narrow an object union by checking a shared tag member. Here the tag is the `kind` field.
type NoteEntry = { kind: "note"; text: string };
type CountEntry = { kind: "count"; value: number };
type Entry = NoteEntry | CountEntry;
function isNote(e: Entry): e is NoteEntry {
return e.kind === "note";
}
const entries: Entry[] = [
{ kind: "note", text: "call supplier" },
{ kind: "count", value: 12 },
{ kind: "note", text: "send invoice" },
];
const notes = entries.filter(isNote);
console.log(notes.map((n) => n.text).join(" | "));Example
function isScore(v: string | number | boolean): v is number {
return typeof v === "number";
}
const raw: (string | number | boolean)[] = ["heat", 30, true, 12, "final", 8];
const scores = raw.filter(isScore);
const total = scores.reduce((sum, s) => sum + s, 0);
console.log(scores.join("+"));
console.log(total);Key points
- A predicate has the form `x is T`, where x is a parameter of the function.
- A check that returns a plain boolean gives the caller no narrowed type.
- `Array.filter` accepts a predicate and returns an array of the narrowed type.
- The predicate function must return true exactly for values of the named type.
- A predicate turns one written check into narrowing that follows the function.
In this example, the predicate isScore narrows the mixed array to a number array. The narrowed array can be joined and summed with no further checks.
Note
TypeScript trusts the predicate, so a wrong check narrows to a wrong type.
Try it Yourself
Edit the code, then press Run.
Running is simulated ยท TypeScript Playground
Exercise
A filter callback has the return type `v is string`. What type does filter return?