Written by John Reilly ✏️
An exciting feature is shipping with TypeScript 4.4. It's called control flow analysis of aliased conditions, which is quite a mouthful.
In this post, we'll unpack this new feature and demonstrate how it contributes to improving the readability of code.
Indirect type narrowing via const
On 24 June 2021, Anders Hejlsberg closed an issue on the TypeScript GitHub repository with the title "Indirect type narrowing via const
." The issue had been open since 2016 and it was closed because it was covered by a pull request addressing control flow analysis of aliased conditional expressions and discriminants.
It's fair to say the TypeScript community was very excited about this, judging from both reactions on the issue:
Not to mention the general delight on Twitter:
Zeh's tweet sums up the significance of control flow analysis of aliased conditions quite nicely:
Lack of type narrowing with consts made me repeat code, or avoid helpfully namef consts, too many times
With this feature, we can write more readable code with less repetition. That's amazing!
Writing more expressive code with TypeScript 4.4
Rather than diving straight into an explanation of what this new language feature is, let's start instead from the position of writing some code and see what's possible with TypeScript 4.4 that we couldn't tackle previously.
Here's a simple function that adds all the parameters it receives and returns the total. It's a tolerant function and allows you to supply numbers in the form of strings as well. So it would successfully process '2'
as it would 2
.
This is, of course, a slightly contrived example, but it's a good way to demonstrate the new feature:
function add(...thingsToAdd: (string | number)[]): number {
let total = 0;
for (const thingToAdd of thingsToAdd) {
if (typeof thingToAdd === 'string') {
total += Number(thingToAdd);
} else {
total += thingToAdd;
}
}
return total;
}
console.log(add(1, '7', '3', 9))
Try it out in the TypeScript playground.
This function, although it works, is not super-expressive. The typeof thingToAdd === 'string'
serves two purposes:
- It narrows the type from
string | number
tostring
- It branches the logic, such that the
string
can be coerced into anumber
and added to the total
You can infer this from reading the code. However, what if we were to rewrite it to capture intent?
Let's try creating a shouldCoerceToNumber
constant that expresses the action we need to take:
function add(...thingsToAdd: (string | number)[]): number {
let total = 0;
for (const thingToAdd of thingsToAdd) {
const shouldCoerceToNumber = typeof thingToAdd === 'string';
if (shouldCoerceToNumber) {
total += Number(thingToAdd);
} else {
total += thingToAdd;
}
}
return total;
}
console.log(add(1, '7', '3', 9))
Try it out in the TypeScript playground.
This is valid code. However, TypeScript 4.3 is choking with an error:
The error being surfaced is:
Operator '+=' cannot be applied to types 'number' and 'string | number'.(2365)
What's happening here? TypeScript does not remember that shouldCoerceToNumber
represents a type narrowing of thingToAdd
from string | number
to string
. So the type of thingToAdd
remains unchanged from string | number
when we write code that depends upon it.
This has terrible consequences. It means we can't write this more expressive code that we're interested in and would be better for maintainers of our codebase. This is what TypeScript 4.4, with our new feature, unlocks.
Let's change the playground to use TypeScript 4.4 instead:
Try it out in the TypeScript playground.
Now that we've made the switch to TypeScript 4.4, delightfully, we no longer have errors. And as the screenshot shows, the thingToAdd
variable has been narrowed to a string
. This is because control flow analysis of aliased conditions is now in play.
We're now writing more expressive code and TypeScript is willing us on our way.
Read more
This feature is a tremendous addition to the TypeScript language. It should have a significant, long-term, positive impact on how people write code with TypeScript.
To read more, check out the excellent TypeScript 4.4 beta release notes. There are also some other exciting features shipping with this release as well.
Thanks very much to the TypeScript team for once again improving the language and making a real contribution to people being able to write readable code.
Top comments (0)