Dev Overflow Logo

Dev Overflow

Global search

Search across questions, answers, users and tags.

Loading...
save

TypeScript: how to narrow a discriminated union inside a filter callback?

clock icon

asked 2 months ago

message icon

1

eye icon

350

Filtering by the discriminant does not narrow the resulting array type:

1type Result =
2 | { kind: "question"; title: string }
3 | { kind: "user"; name: string }
4
5const questions = results.filter((r) => r.kind === "question")
6// still Result[], not { kind: "question"; title: string }[]
1type Result =
2 | { kind: "question"; title: string }
3 | { kind: "user"; name: string }
4
5const questions = results.filter((r) => r.kind === "question")
6// still Result[], not { kind: "question"; title: string }[]

1 Answer

filter cannot narrow on its own — it returns the same element type unless the callback is a type predicate. Write one:

1const questions = results.filter(
2 (r): r is Extract<Result, { kind: "question" }> => r.kind === "question",
3)
1const questions = results.filter(
2 (r): r is Extract<Result, { kind: "question" }> => r.kind === "question",
3)

TypeScript 5.5+ can infer this automatically when the predicate is a simple, directly-returned comparison, so on a recent compiler your original code may already narrow. If it doesn't, the explicit annotation always works.

1

of 1

Write your answer here

Introduce the problem and expand on what you've put in the title.

Top Questions