TypeScript 5.5 made common filter pipelines less noisy through inferred type predicates.
Older versions often needed a helper after mapping optional values:
const scores = studentIds
.map((id) => scoreByStudent.get(id))
.filter((score) => score !== undefined)
const average = scores.reduce((sum, score) => sum + score, 0) / scores.length
A reusable predicate worked:
function isDefined<T>(value: T | undefined): value is T {
return value !== undefined
}
The improvement is not permission to write vague filters. Truthiness can remove valid zeroes:
const scores = [0, 82, 91, undefined].filter((score) => !!score)
Use the condition that expresses the actual boundary:
const scores = [0, 82, 91, undefined].filter(
(score) => score !== undefined,
)
The compiler can now carry more of the ordinary case without an assertion:
const visibleItems = items
.map((item) => item.details)
.filter((details) => details !== undefined)
return visibleItems.map((details) => (
<DetailCard key={details.id} details={details} />
))
Inferred predicates do not excuse side effects or unclear domain logic inside filters. Keep predicates small and truthful.
The feature is modest. Its value is cumulative: fewer helper functions, fewer assertions, and calmer array pipelines.
Related posts

About Jeremy London
Engineering leader and builder in Denver. I write about AI platforms, agents, security, reliability, homelab infrastructure, and the parts of engineering work that have to survive production.