Speed improvements

TypeScript 3.5 contains certain optimizations over TypeScript 3.4 for type-checking more efficiently. These improvements are significantly more pronounced in editor scenarios where type-checking drives operations like code completion lists.

TypeScript 3.5 improves on 3.4’s --incremental build mode, by saving information about how the state of the world was calculated - compiler settings, why files were looked up, where files were found, etc. In scenarios involving hundreds of projects using TypeScript’s project references in --build mode, !

For more details, you can see the pull requests to

TypeScript 3.5 introduces the new Omit helper type, which creates a new type with some properties dropped from the original.

Here we were able to copy over all the properties of Person except for location using the Omit helper.

For more details, , as well as the change to use Omit for object rest.

In TypeScript 3.4 and earlier, certain excess properties were allowed in situations where they really shouldn’t have been. For instance, TypeScript 3.4 permitted the incorrect name property in the object literal even though its types don’t match between Point and .

  1. ts
    type Point = {
    x: number;
    y: number;
    };
    type Label = {
    name: string;
    };
    const thing: Point | Label = {
    x: 0,
    y: 0,
    name: true // uh-oh!
    };

In TypeScript 3.5, the type-checker at least verifies that all the provided properties belong to some union member and have the appropriate type, meaning that the sample above correctly issues an error.

Note that partial overlap is still permitted as long as the property types are valid.

  1. ts
    const pl: Point | Label = {
    x: 0,
    y: 0,
    name: "origin" // okay
    };

The --allowUmdGlobalAccess flag

In TypeScript 3.5, you can now reference UMD global declarations like

from anywhere - even modules - using the new --allowUmdGlobalAccess flag.

This mode adds flexibility for mixing and matching the way 3rd party libraries, where globals that libraries declare can always be consumed, even from within modules.

For more details, see the pull request on GitHub.

In TypeScript 3.4 and prior, the following example would fail:

  1. ts
    type S = { done: boolean; value: number };
    type T = { done: false; value: number } | { done: true; value: number };
    declare let source: S;
    declare let target: T;
    target = source;
  1. ts
    interface Foo {
    kind: "foo";
    value: string;
    }
    interface Bar {
    kind: "bar";
    value: number;
    }
    function doSomething(x: Foo | Bar) {
    if (x.kind === "foo") {
    x.value.toLowerCase();
    }
    }
    // uh-oh - luckily TypeScript errors here!
    doSomething({
    kind: "foo",
    value: 123
    });

However, this was a bit overly strict for the original example. If you figure out the precise type of any possible value of S, you can actually see that it matches the types in T exactly.

In TypeScript 3.5, when assigning to types with discriminant properties like in T, the language actually will go further and decompose types like S into a union of every possible inhabitant type. In this case, since boolean is a union of true and false, S will be viewed as a union of { done: false, value: number } and { done: true, value: number }.

For more details, you can .

Higher order type inference from generic constructors

In TypeScript 3.4, we improved inference for when generic functions that return functions like so:

took other generic functions as arguments, like so:

    Instead of a relatively useless type like (x: {}) => Box<{}[]>, which older versions of the language would infer, TypeScript 3.4’s inference allows newFn to be generic. Its new type is .

    TypeScript 3.5 generalizes this behavior to work on constructor functions as well.

    1. ts
      class Box<T> {
      kind: "box";
      value: T;
      constructor(value: T) {
      this.value = value;
      }
      }
      class Bag<U> {
      kind: "bag";
      value: U;
      constructor(value: U) {
      this.value = value;
      }
      }
      function composeCtor<T, U, V>(
      F: new (x: T) => U,
      G: new (y: U) => V
      ): (x: T) => V {
      return x => new G(new F(x));
      }
      let f = composeCtor(Box, Bag); // has type '<T>(x: T) => Bag<Box<T>>'
      let a = f(1024); // has type 'Bag<Box<number>>'

    To learn more, .