All Things Typescript Newsletter - Issue #14 - Understanding Type Widening
Good morning; I hope you had a fabulous weekend. In this issue, I wanted to cover Type Widening, a sub-topic of Type Inference in Typescript and one I feel we need to understand to get the most out of Typescript. For more information, check the content in the next section.
I am looking to launch a discord server for All Things Typescript this week, where we can learn and help each other learn Typescript. In the discord, you will be able to post your questions, answer if you can, and suggest topics for future All Things Typescript issues. On top of that, there will be weekly fireside discussions, where we can all meet, get to know each other, and discuss various topics in Typescript.
That’s it from me, and I hope you will enjoy this week’s issue of Typescript, au revoir 🙋🏿♂️.
Understanding Type Widening in Typescript
You don’t hear much about Type Widening as much as you do about Type narrowing in Typescript. Type widening is the opposite of Type narrowing, and it’s used by Typescript to determine the type to assign to a variable whose type is not explicitly annotated but is left for Typescript to infer.
Take the following variables:
const x = "1";
let y = "1"
What do you think their types are? You would expect both to be strings, but the first one (x
) is a string literal of "1"
while the second one is a string
.
Type Widening in Action
Why? Since the first variable - x
- is defined using const
, Typescript inferred that it can’t be re-assigned, and there is no need to widen it beyond the literal type of "1"
. While the second variable - y
- is defined using let
and can be re-assigned; hence its type is widened to allow all variables that are strings to be assigned.
If we were to take the variable x
definition, it is a little straightforward to understand why typescript chose to infer the type it did, as its value cannot be changed. But when it comes to the variable y
, the possible types range from:
a more strict type definition of a literal type of
"1"
- This allows it only to be assigned the value"1"
Probably not what you had in mind.a more sensible type definition of
string
- This restricts the types of values that can be assigned to this variable to be only strings, which"1"
is a subtype of, and probably what you had in mind.an even broader
any
- this would allow the variabley
to be assigned anything from numbers to boolean.
When it comes to type inference, Typescript will try to strike a balance between being too strict and too broad by using the information it has at its hand. So, when you use const, Typescript can convert the type to a literal type as const
indicates the variable is immutable. And if you use let
, Typescript will use this information (let
defines a mutable variable) to widen the type to include a much broader but sensible type definition for the variable in question.
For objects and arrays, this behavior isn’t replicated. When you define an object or an array using const, Typescript doesn’t infer the type to its narrowest type, i.e., a Tuple for an array and an immutable object for an object. This is because while a variable defining an object cannot be re-assigned a new value, the object properties can be modified, and new properties can be added. The same goes for an array, where we can still push new values to it and modify existing ones.
There are several scenarios where typescript doesn’t do Type widening. This is because typescript can derive more information about the variable being defined. The first scenario is when you provide type annotation, typescript will use the type annotation as the type for the variable. If we take a look at variable x
from above, if we assigned it a type annotation of string
Typescript will not change that, as shown below.
And the second scenario is when Typescript can derive more information about the variable from the usage context. This is commonly seen in functional parameters, where Typescript will use the parameter type of the function as the variable type of the variable you are passing in without widening it.
And the third situation is when we use const assertions. When we use const assertions on an object or an array, Typescript infers the type of the variable to its narrowest possible type. This means that an object becomes a read-only object, i.e., the fields cannot be mutated, and an array becomes a read-only tuple, as shown below:
For more information, you can learn more about const assertions here.
Conclusion
In this week’s topic, we learned about Type Widening in Typescript and how Typescript tries to assign the best possible type for the variable with the information it has available to it. If you want to learn about type inference, check out my previous issue here.
Support My Work 😃
Please consider supporting my work by buying me a cup of coffee (or several cups 😃) here if you want to support my work. Thank you.
Announcements 📢
Announcing TypeScript 4.8 Beta - TypeScript
Today we’re announcing our beta release of TypeScript 4.8! To get started using the beta, you can get it through NuGet, or- use npm with the following command: npm install -D [email protected] You can also get editor support by Downloading for Visual Studio 2022/2019 Following directions for Visual Studio Code.
Articles
TypeScript for Deno: Types and Typing
It is always necessary to update and learn new things that’s why I made this series of notes for those who want to get into the world of TypeScript and especially to make applications with Deno. Obviously, this information is useful if you want to program with Nest.
Advanced TypeScript Cheat Sheet for Types, Interfaces, Control Flow, and More
Debugging and troubleshooting is the most annoying part of software development but TypeScript handles the inadequacies with grace. That’s why almost 60% of JavaScript developers use it and 22% of them wish to try it.
Leveraging TypeScript to Create Better Polymorphic React Components
Reusable components are one of the key concepts in React — where you write a component once and get to reuse them multiple times.
Typescript - Advanced Types
Intersection types allow us to combine multiple types into one type. In the below code consider we combine the left and the right type to get the combined Intersection Type. This intersection can also be achieved using interfaces.
The Case Against Glorifying Developers for Wrong Reasons | by Manvik Kathuria | Jun, 2022 | Better Programming
It was a sunny Friday evening, and I was busy doing the admin chores of backlog and sprint planning. Then came a slack notification that read something like this. The team’s manager wrote this for…
Demystifying edge functions - LogRocket Blog
Learn all about edge computing and edge functions, and how they’re enjoying increasing popularity for their wide variety of uses.