09 Aug 2024
4 min

The most important new features introduced by TypeScript 5.5

Like many things, Typescript still expands to provide the best possible solution and to make the development process smoother. Let’s review what has been changed and how we can use it in our daily development process.

Support for new methods in Set object.


Recently, JavaScript introduced new Set methods such as union() and difference(), providing native functionality for common set operations. However, TypeScript did not support these methods initially. With the release of TypeScript 5.5, full support for these new methods has been implemented, enabling developers to use it seamlessly within TypeScript projects. Take a look at this case:

const bikes = new Set(["Wheeler", "Merida"]);
const cars = new Set(["Volkswagen", "Saab"]);


const myGarage = bikes.union(car);// { 'Volkswagen', 'Saab', 'Wheeler', 'Merida'}

If you are using a version lower than 5.5, the TypeScript Compiler would raise this error when you attempt to use any of these methods.

Property 'union' does not exist on type 'Set<string>'.(2339)

Remember that upgrading TypeScript alone will not solve this issue. You must ensure that you set an appropriate target for the ECMAScript version in your tsconfig.json to get rid of this error. 

Improved Type Predicates

This improvement can definitely change the way we develop our code, especially when we work with arrays. Let’s consider the the following case:

const grades = [3, 4, "A", "C", 2, 5];

As we can see, there is an array that consists of grades, which can be a number or a string. Let’s assume you want to filter out numeric grades from an array. In older TypeScript versions, you’d need to write:

const nonNumericGrades = grades.filter((grade): grade is string => typeof grade === 'string' );  // Output: string[]

With improved type predicates, TypeScript automatically narrows the type, so the filtered nonNumericGrades array is inferred as string[], without the need for additional type annotations or predicates.

const nonNumericGrades = grades.filter((grade) =>
 typeof grade === 'string'); // Output: string[]

If you decide to update the TypeScript version in your project you have to be watchful. In a few cases you might see a problem. Let’s consider the following case:

const values = [3, false, 'string'].filter((x) => typeof x !== 'boolean');
values.push(true);

In the previous version of TypeScript this code worked perfectly fine. In the recent one, the following error will be shown:

Argument of type 'boolean' is not assignable to parameter of type 'string | number'.(2345)

This happens because now TypeScript is more precise.

TypeScript 5.5:

const values: (string | number)[]

The previous version of TypeScript:

const values: (string | number | boolean)[]

You can get rid of this error in this way:

const values: (string | number | boolean)[] = [3, false, 'string'].filter((x) => typeof x !== 'boolean');

Influence On Another Libs

As an extension of the previous section, we should know that we can take advantage of improved type predicates not only in pure TS files but also, for example, in files that use RxJS lib. Let’s consider the following case.

class Example {
  private _myArr = of("11", 1);
}

As we can we it is an observable created by using of operator. Similarly to the previous case, we want to filter by the value type.

this._myArr.
  pipe(
    filter((el) => {
      return typeof el !== 'string'
    }),
    tap((filteredElement) => 
      console.log(filteredElement * 10)
    )
  ).subscribe();

In the previous version of TypeScript this error would be shown:

The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.(2362)

Syntax Checking On Regular Expressions.

With the new version of Typescript, regular expressions and their syntax are no longer skipped. From now on TypeScript handles with them and performs basic syntax checks. This is a huge improvement but you have to be watchful. The syntax checks are performed only for regular expression literals. It does not work with the RegExp object constructor as it is described 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

Improved Constant Indexed Access Type  Narrowing 

The next big step in the process of improving TypeScript is easier access to object properties, which is provided by better type narrowing. Let’s consider the following case:

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 have created a function that checks if the object’s property value type is a number, and if so,  it returns an object with a multiplied property’s value. In any other case, it returns an object with a  hardcoded property value. Developer were able to see the following error until now:

The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.(2362)

This error does not occur in the recent update of TypeScript. What is more, we don’t need any workaround like that:

const value = Number(obj[key]);
    return {
        key: value * 10
    };

Improved Type Imports in JSDoc

The latest version of Typescript supports a new @Import comment tag. This feature has been introduced to restrain the problems with imported types, as they do not exist during the runtime of our application. Let’s see below:

/** @import { ObjType } from "types" */


/**
* @param { ObjType } objExample
*/


function myFunc(objExample) {
   // ...
}

Before the recent release, developers had to consider making workarounds like this:

/**
* @param {import("Types").ObjType} objExample
*/

As we can see, there is no need for that quite ugly workaround.

Package Size

Last but not least, the package size has been reduced due to rebuilding tsserver.js and typingInstaller.js files. These files are now part of the public API and they do not produce a standalone bundle.

Before After Difference(%)
Packed 5.51 MiB 3.76 MiB 31.66%
Unpacked 30.18 MiB 20.36 MiB 32.55%

What about Angular?

If you are an Angular Developer and you really want to take advantage of new TypeScript features, you should update your Angular version to 18.1. Since this version, the new features are supported. You can read more about new changes introduced in Angular here

Summary

As described, the latest TypeScript version introduces many changes. It is worth mentioning that with each new iteration, TypeScript becomes a better tool for our daily work. It is too early to talk about the next iteration, but we hope that it will be as fruitful as the recent one.

Thank you for reading my article.

Share this post

Sign up for our newsletter

Stay up-to-date with the trends and be a part of a thriving community.