The Typescript feature we all wanted
TLDR: Inferred Type Predicates are now available in Typescript 5.5 Beta. In this article, I’ll explain the much-awaited feature and how it’ll help you write more type-safe code.
Introduction
For the most part, Typescript’s control flow analysis does an impressive job of monitoring how the type of a variable changes as it moves through your code.
For example, consider the trivial function that receives either a string
or number
below:
function echo (val: string| number) {
if (typeof val === 'string') {
console.log(`STRING: ${val}`)
return
}
console.log(val)
}
In this basic example, Typescript can conveniently tell that the variable on line 3 is of type string
and the variable on line 7 of type number
.
The reason this is important is that Typescript can spot bugs based on this inferred type, i.e., if we used a wrong string method in line 7, we’d get an error.
This is wonderful.
Let’s now consider a case where Typescript has historically failed.
What the TS??
Consider this perfectly written code:
const values = ["Hello", "World", null, undefined, "Hooray"]
const filteredValues = values.filter((v) => typeof v === 'string')
From a developer’s perspective, this reads nicely.
- We have a list of values containing either strings or
null
andundefined
- We
filter
outnull
andundefined
so we can work with the remaining string values
However, Typescript is confused.
The inferred type of filteredValues
is still (string | null | undefined)[]
even though we explicitly filtered null
and undefined
If you’ve battled this behaviour in the past, you’re not alone.
While there are workarounds to this, from a Typescript control flow analysis perspective, this is code that should simply work out of the box.
Inferred Type Predicates
When I spoke about workarounds, one way to fix this would be to write a type predicate.
A type predicate is really just a function that returns a boolean and is used to narrow down types.
OK, back to the subject of discussion. Why should we need workarounds in the first place?
Well, there’s good news. From Typescript 5.5 Beta, Typescript will now infer type predicates out of the box!
In practical terms, this means the code we wrote earlier now works out of the box. No workarounds, no hacks, no nothing.
No errors!
Conclusion
This seemingly simple change has been seven years in the making. Yes, seven — well, since the initial issue was open.
Typescript 5.5 beta ships with plenty of changes, but none excites me as much as the humble inferred type predicates. Every so often, it’s the simple things that make a difference. At least in my case.
=============== SHAMELESS PLUG ⬇️ ===============
I’m launching a passion project soon and would appreciate your genuine feedback and support. Please hit «notify me» here: https://www.producthunt.com/products/bestregards
=============== =============== ===============