Today we’re announcing the availabilty of TypeScript 3.9 Beta!
To get started using the beta, you can get it
For this release our team been has been focusing on performance, polish, and stability. We’ve been working on speeding up the compiler and editing experience, getting rid of friction and papercuts, and reducing bugs and crashes. We’ve also received a number of useful and much-appreciated features and fixes from the external community!
Promise unwrapping works in JavaScript.We initially anticipated shipping awaited in TypeScript 3.9, but as we’ve run early TypeScript builds with existing codebases, we’ve realized that the feature needs more design work before we can roll it out to everyone smoothly. As a result, we’ve decided to pull the feature out of our main branch until we feel more confident. We’ll be experimenting more with the feature, but we won’t be shipping it as part of this release.
Speed Improvements
TypeScript 3.9 ships with many new speed improvements. Our team has been focusing on performance after observing extremely poor editing/compilation speed with packages like material-ui and styled-components. We’ve dived deep here, with a series of different pull requests that optimize certain pathological cases involving large unions, intersections, conditional types, and mapped types.
Each of these pull requests gains about a 5-10% reduction in compile times on certain codebases. In total, we believe we’ve achieved around a 40% reduction in material-ui’s compile time!
We also have some changes to file renaming functionality in editor scenarios. We heard from the Visual Studio Code team that when renaming a file, just figuring out which import statements needed to be updated could take between 5 to 10 seconds. TypeScript 3.9 addresses this issue by , the contributor who implemented this feature. For more information, you can take a look at from
Editor Improvements
The TypeScript compiler not only powers the TypeScript editing experience in most major editors, it also powers the JavaScript experience in the Visual Studio family of editors and more. Using new TypeScript/JavaScript functionality in your editor will differ depending on your editor, but
- Visual Studio Code supports to stay on the bleeding edge (which is typically very stable).
- Visual Studio 2017/2019 have .
- Sublime Text 3 supports .
Code Actions Preserve Newlines
TypeScript’s refactorings and quick fixes often didn’t do a great job of preserving newlines. As a really basic example, take the following code.
const maxValue = 100;
/*start*/
for (let i = 0; i <= maxValue; i++) {
// First get the squared value.
let square = i ** 2;
// Now print the squared value.
console.log(square);
}
/*end*/
If we highlighted the range from
/*start*/to/*end*/in our editor to extract to a new function, we’d end up with code like the following.
const maxValue = 100;
printSquares();
function printSquares() {
for (let i = 0; i <= maxValue; i++) {
// First get the squared value.
let square = i ** 2;
// Now print the squared value.
console.log(square);
}
}

That’s not ideal – we had a blank line between each statement in our
forloop, but the refactoring got rid of it! TypeScript 3.9 does a little more work to preserve what we write.
const maxValue = 100;
printSquares();
function printSquares() {
for (let i = 0; i <= maxValue; i++) {
// First get the squared value.
let square = i ** 2;
// Now print the squared value.
console.log(square);
}
}

You can see more about the implementation .
Breaking Changes
Parsing Differences in Optional Chaining and Non-Null Assertions
TypeScript recently implemented the optional chaining operator, but we’ve received user feedback that the behavior of optional chaining (
?.) with the non-null assertion operator (!) is extremely counter-intuitive.
Specifically, in previous versions, the code
foo?.bar!.baz
was interpreted to be equivalent to the following JavaScript.
(foo?.bar).baz
In the above code the parentheses stop the “short-circuiting” behavior of optional chaining, so if
fooisundefined, accessingbazwill cause a runtime error.
The Babel team who pointed this behavior out, and most users who provided feedback to us, believe that this behavior is wrong. We do too! The thing we heard the most was that the
!operator should just “disappear” since the intent was to removenullandundefinedfrom the type ofbar.
In other words, most people felt that the original snippet should be interpreted as
foo?.bar.baz
which just evaluates to
undefinedwhenfooisundefined.
This is a breaking change, but we believe most code was written with the new interpretation in mind. Users who want to revert to the old behavior can add explicit parentheses around the left side of the
!operator.
(foo?.bar)!.baz
}and>are Now Invalid JSX Text Characters
The JSX Specification forbids the use of the
}and>characters in text positions. TypeScript and Babel have both decided to enforce this rule to be more comformant. The new way to insert these characters is to use an HTML escape code (e.g.<div> 2 > 1 </div>) or insert an expression with a string literal (e.g.<div> 2 {">"} 1 </div>).
Luckily, thanks to the , you’ll get an error message along the lines of
CODEUnexpected token. Did you mean `{'>'}` or `>`?
Unexpected token. Did you mean `{'}'}` or `}`?
For example:
let directions = <div>Navigate to: Menu Bar > Tools > Options</div>
// ~ ~
// Unexpected token. Did you mean `{'>'}` or `>`?
That error message came with a handy quick fix, and thanks to if you have a lot of errors.
Stricter Checks on Intersections and Optional Properties
Generally, an intersection type like
A & Bis assignable toCif eitherAorBis assignable toC; however, sometimes that has problems with optional properties. For example, take the following:
interface A {
a: number; // notice this is 'number'
}
interface B {
b: string;
}
interface C {
a?: boolean; // notice this is 'boolean'
b: string;
}
declare let x: A & B;
declare let y: C;
y = x;
In previous versions of TypeScript, this was allowed because while
Awas totally incompatible withC,Bwas compatible withC.
In TypeScript 3.9, so long as every type in an intersection is a concrete object type, the type system will consider all of the properties at once. As a result, TypeScript will see that the
aproperty ofA & Bis incompatible with that ofC:
CODEType 'A & B' is not assignable to type 'C'.
Types of property 'a' are incompatible.
Type 'number' is not assignable to type 'boolean | undefined'.
For more information on this change, .
Getters/Setters are No Longer Enumerable
In older versions of TypeScript,
getandsetaccessors in classes were emitted in a way that made them enumerable; however, this wasn’t compliant with the ECMAScript specification which states that they must be non-enumerable. As a result, TypeScript code that targeted ES5 and ES2015 could differ in behavior.
Thanks to , TypeScript 3.9 now conforms more closely with ECMAScript in this regard.
Type Parameters That Extend
anyNo Longer Act asany
In previous versions of TypeScript, a type parameter constrained to
anycould be treated asany.
function foo<T extends any>(arg: T) {
arg.spfjgerijghoied; // no error!
}
This was an oversight, so TypeScript 3.9 takes a more conservative approach and issues an error on these questionable operations.
function foo<T extends any>(arg: T) {
arg.spfjgerijghoied;
// ~~~~~~~~~~~~~~~
// Property 'spfjgerijghoied' does not exist on type 'T'.
}
export *is Always Retained
In previous TypeScript versions, declarations like
export * from "foo"would be dropped in our JavaScript output iffoodidn’t export any values. This sort of emit is problematic because it’s type-directed and can’t be emulated by Babel. TypeScript 3.9 will always emit theseexport *declarations. In practice, we don’t expect this to break much existing code.
What’s Next?
You can keep posted on the progress of the TypeScript 3.9 release on .
Happy Hacking!
– Daniel Rosenwasser and the TypeScript Team
The post .
↗ Original-Artikel auf devblogs.microsoft.com lesenVollständiger Original-BerichtAusführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf devblogs.microsoft.com.
SOCIAL SHARE CARD GENERATOR