New Set Methods Now Supported
JavaScript recently added several new methods to the Set object, such as union() and difference(), bringing native support for common set operations. Initially, TypeScript did not include type definitions for these methods. With the arrival of TypeScript 5.5, complete support has been added, allowing developers to use them without friction in their TypeScript projects. Consider this example:
const bikes = new Set(["Wheeler", "Merida"]);
const cars = new Set(["Volkswagen", "Saab"]);
const myGarage = bikes.union(car);// { 'Volkswagen', 'Saab', 'Wheeler', 'Merida'}
In versions prior to 5.5, attempting to call any of these methods would result in an error from the TypeScript compiler.
Property 'union' does not exist on type 'Set<string>'.(2339)
Keep in mind that simply updating TypeScript is not enough. You also need to configure the appropriate ECMAScript target in your tsconfig.json to eliminate this error.
Better Type Predicate Inference
This enhancement has the potential to significantly alter how we write code, particularly when handling arrays. Consider the following scenario:
const grades = [3, 4, "A", "C", 2, 5];
Here, we have an array of grades that may be either numbers or strings. Suppose you want to filter out the numeric values. In earlier TypeScript versions, you'd have to write:
const nonNumericGrades = grades.filter((grade): grade is string => typeof grade === 'string' ); // Output: string[]
Thanks to improved type predicates, TypeScript can now automatically infer the type. The resulting nonNumericGrades array is correctly typed as string[], eliminating the need for explicit type annotations or custom type guard functions.
const nonNumericGrades = grades.filter((grade) =>
typeof grade === 'string'); // Output: string[]
Be cautious if you decide to upgrade your project's TypeScript version. There are a few cases where you might encounter issues. Consider the following example:
const values = [3, false, 'string'].filter((x) => typeof x !== 'boolean');
values.push(true);
This code worked without any problems in earlier TypeScript versions. However, the latest version will throw the following error:
Argument of type 'boolean' is not assignable to parameter of type 'string | number'.(2345)
This is because TypeScript has become more precise in its type checking.
With TypeScript 5.5:
const values: (string | number)[]
With the previous version:
const values: (string | number | boolean)[]
You can resolve this error using the following approach:
const values: (string | number | boolean)[] = [3, false, 'string'].filter((x) => typeof x !== 'boolean');
Impact on Other Libraries
Building on the previous point, these improved type predicates are not limited to plain TypeScript files. They also work in projects that use other libraries, such as RxJS. Take a look at this example:
class Example {
private _myArr = of("11", 1);
}
As shown, this is an observable created with the of operator. Similar to the previous case, we want to filter based on the value type.
this._myArr.
pipe(
filter((el) => {
return typeof el !== 'string'
}),
tap((filteredElement) =>
console.log(filteredElement * 10)
)
).subscribe();
In the previous TypeScript version, you would have seen this error:
The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.(2362)
Regular Expression Syntax Validation
The new TypeScript version no longer skips regular expressions during compilation. It now performs basic syntax checks on them. This is a significant improvement, but there is a caveat: syntax checking only applies to regular expression literals. It does not validate patterns passed to the RegExp constructor, as illustrated below:
const regPattern = /angular18(/; //error: ')' expected.
const regExp = RegExp(" /angular18(/"); //no error thrown
//Typescript Version Lower than 5.5:
const regPattern = /angular18(/; /no error thrown
Enhanced Narrowing for Indexed Access Types
Another major step forward is easier access to object properties, made possible by better type narrowing. Consider the following function:
type ObjectType = Record<number | string, number | string>;
const someObject: ObjectType = {
10: 30
};
function multiplyVal(obj: ObjectType, key: number | string) {
if (typeof obj[key] === "number") {
return {
key: obj[key] * 10
};
} else {
return {
key: 'Key is not a number'
};
}
}
We've defined a function that checks if an object property value is a number. If so, it returns an object with that property multiplied; otherwise, it returns an object with a hardcoded value. Until now, developers would encounter the following error:
The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.(2362)
This error is gone in the latest TypeScript update. Moreover, workarounds like the one below are no longer necessary:
const value = Number(obj[key]);
return {
key: value * 10
};
New JSDoc Import Tag
The latest TypeScript release introduces a new @import comment tag. This feature addresses problems related to imported types, which are not present during application runtime. See the example below:
/** @import { ObjType } from "types" */
/**
* @param { ObjType } objExample
*/
function myFunc(objExample) {
// ...
}
Before this release, developers had to resort to workarounds such as:
/**
* @param {import("Types").ObjType} objExample
*/
As you can see, that rather awkward workaround is now obsolete.
Reduced Package Footprint
Finally, the package size has been decreased. This was achieved by rebuilding tsserver.js and typingInstaller.js. These files are now part of the public API and no longer generate a standalone bundle.
| Before | After | Difference(%) | |
| Packed | 5.51 MiB | 3.76 MiB | 31.66% |
| Unpacked | 30.18 MiB | 20.36 MiB | 32.55% |
Angular Compatibility
For Angular developers who want to leverage these new TypeScript features, you should update to Angular 18.1. Starting with this version, the new capabilities are fully supported. More details on the Angular changes can be found here.
Conclusion
The latest TypeScript release introduces a wide range of improvements. With each new iteration, TypeScript proves to be an increasingly robust tool for everyday development. While it's too early to speculate on the next release, we remain hopeful that it will be just as productive.
