Was this page helpful?

TypeScript 3.5

Speed improvements

TypeScript 3.5 introduces several optimizations around type-checking and incremental builds.

Type-checking speed-ups

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.

--incremental improvements

TypeScript 3.5 improves on 3.4’sincremental 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,we’ve found that the amount of time rebuilding can be reduced by as much as 68% compared to TypeScript 3.4!

For more details, you can see the pull requests to

TheOmit helper type

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

ts
typePerson = {
name:string;
age:number;
location:string;
};
typeQuantumPerson =Omit<Person,"location">;
// equivalent to
typeQuantumPerson = {
name:string;
age:number;
};

Here we were able to copy over all the properties ofPerson except forlocation using theOmit helper.

For more details,see the pull request on GitHub to addOmit, as well asthe change to useOmit for object rest.

Improved excess property checks in union types

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 incorrectname property in the object literal even though its types don’t match betweenPoint andLabel.

ts
typePoint = {
x:number;
y:number;
};
typeLabel = {
name:string;
};
constthing:Point |Label = {
x:0,
y:0,
name:true// uh-oh!
};

Previously, a non-discriminated union wouldn’t haveany excess property checking done on its members, and as a result, the incorrectly typedname property slipped by.

In TypeScript 3.5, the type-checker at least verifies that all the provided properties belong tosome 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.

ts
constpl:Point |Label = {
x:0,
y:0,
name:"origin"// okay
};

The--allowUmdGlobalAccess flag

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

export as namespace foo;

from anywhere - even modules - using the newallowUmdGlobalAccess 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.

Smarter union type checking

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

ts
typeS = {done:boolean;value:number };
typeT = {done:false;value:number } | {done:true;value:number };
declareletsource:S;
declarelettarget:T;
target =source;

That’s becauseS isn’t assignable to{ done: false, value: number } nor{ done: true, value: number }.Why?Because thedone property inS isn’t specific enough - it’sboolean whereas each constituent ofT has adone property that’s specificallytrue orfalse.That’s what we meant by each constituent type being checked in isolation: TypeScript doesn’t just union each property together and see ifS is assignable to that.If it did, some bad code could get through like the following:

ts
interfaceFoo {
kind:"foo";
value:string;
}
interfaceBar {
kind:"bar";
value:number;
}
functiondoSomething(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 ofS, you can actually see that it matches the types inT exactly.

In TypeScript 3.5, when assigning to types with discriminant properties like inT, the language actuallywill go further and decompose types likeS into a union of every possible inhabitant type.In this case, sinceboolean is a union oftrue andfalse,S will be viewed as a union of{ done: false, value: number } and{ done: true, value: number }.

For more details, you cansee the original pull request on GitHub.

Higher order type inference from generic constructors

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

ts
functioncompose<T,U,V>(f: (x:T)=>U,g: (y:U)=>V): (x:T)=>V {
returnx=>g(f(x));
}

took other generic functions as arguments, like so:

ts
functionarrayify<T>(x:T):T[] {
return [x];
}
typeBox<U> = {value:U };
functionboxify<U>(y:U):Box<U> {
return {value:y };
}
letnewFn =compose(arrayify,boxify);

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

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

ts
classBox<T> {
kind:"box";
value:T;
constructor(value:T) {
this.value =value;
}
}
classBag<U> {
kind:"bag";
value:U;
constructor(value:U) {
this.value =value;
}
}
functioncomposeCtor<T,U,V>(
F:new (x:T)=>U,
G:new (y:U)=>V
): (x:T)=>V {
returnx=>newG(newF(x));
}
letf =composeCtor(Box,Bag);// has type '<T>(x: T) => Bag<Box<T>>'
leta =f(1024);// has type 'Bag<Box<number>>'

In addition to compositional patterns like the above, this new inference on generic constructors means that functions that operate on class components in certain UI libraries like React can more correctly operate on generic class components.

ts
typeComponentClass<P> =new (props:P)=>Component<P>;
declareclassComponent<P> {
props:P;
constructor(props:P);
}
declarefunctionmyHoc<P>(C:ComponentClass<P>):ComponentClass<P>;
typeNestedProps<T> = {foo:number;stuff:T };
declareclassGenericComponent<T>extendsComponent<NestedProps<T>> {}
// type is 'new <T>(props: NestedProps<T>) => Component<NestedProps<T>>'
constGenericComponent2 =myHoc(GenericComponent);

To learn more,check out the original pull request on GitHub.

The TypeScript docs are an open source project. Help us improve these pagesby sending a Pull Request

Contributors to this page:
DRDaniel Rosenwasser  (51)
OTOrta Therox  (11)
EIEugene Ilyin  (1)
JBJack Bates  (1)
1+

Last updated: Dec 16, 2025