The recent release of TypeScript 4.0 offers a smorgasbord of improvements including improvements to coding editor experience, build scenarios and support for variadic tuple types. Let’s take a closer look at some of these improvements a developer can make use of in this latest release.

Support for Variadic Tuple Types

TypeScript 4.0 has made two different updates that allow for more flexibility in typing tuples. The first update allows generic types to use the spread syntax when defining a tuple, this is useful for scenarios involving generic spreads of tuples or arrays where the type is not necessarily known. The second update allows for rest elements anywhere in a tuple, not just at the end. A great use case for these improvements can be found when defining a type for the following function.

function concat(arr1, arr2) {
   return [...arr1, ...arr2];

Before this release, in order to correctly type this, one would have to create a type definition for all possible scenarios for the array types. If you try to list out some definitions for this function you will quickly be able to list out infinite definitions based on how concat is used. For instance:

function concat<A, B, C, D, E, F>(arr1: [A, B, C, D], arr2: [E, F]): [A, B, C, D, E, F] {
   return [...arr1, ...arr2];

This improvement allows a developer to define a much more flexible concat function. Instead one could now define this function to more accurately depict this scenario:

function concat<T extends Arr, U extends Arr>(arr1: T, arr2: U): [...T, ...U] {
   return [...arr1, ...arr2];

Labeled Tuple Elements

TypeScript 4.0 brings improved readability with the ability to label tuple elements, while this does not improve type checking it will be useful to help your code legibility for fellow developers. For example suppose you have the tuple FlightTime, with a departure and arrival time, this can now be written as the following:

type FlightTime = [departure: Date, arrival: Date];

Imagine using a function with this tuple as the parameter, when using such a function IntelliSense can now let you know the labels for the tuple values, pretty handy!

Implied property type from constructors

Developers can now enable the noImplicitAny option and have TypeScript imply the type of a class property from the constructor. Previously TypeScript would have assumed a type of any if none was specified.

class Coffee {
    // Previously this type was implied as any
    // Now it's inferred to type `number`!

    constructor(ounces: number) {
        this.ounces = ounces;

Other 4.0 TypeScript Changes

There are a couple of other updates that should be noted in this release. 

  • For large TypeScript projects using VSCode there were significant loading delays upward of one minute, this has been shaved down to a couple seconds by a partial loading experience in which only the current files the editor has open will be processed until the full language service is ready.
  • Smarter auto imports have been implemented to auto-include type dependencies that are not in the node_modules/@types folder. Before this, auto-imports from packages not in the node_modules/@types folder only worked after there was at least one explicit import somewhere else in the project.
  • Speed improvements when using build mode with --incremental and –-noEmitOnError flags enabled, previously the build time with these flags has been very slow, as there was no information that was cached in the .tsbuildinfo file.
  • The JS Doc label /** @deprecated */ can now be used to signify to editors that certain declarations are deprecated. For instance, in VSCode the value would be shown with a strike-though.

Craving more TypeScript knowledge? Check out our Definitive TypeScript Guide for a deeper dive. Alternatively, if you need some help, feel free to reach out to us. If you are upgrading TypeScript versions there are a few breaking changes, so make sure to check out the release notes before the upgrade.