{"componentChunkName":"component---src-templates-documentation-tsx","path":"/docs/handbook/release-notes/typescript-3-9.html","result":{"data":{"allSitePage":{"nodes":[{"path":"/dev-404-page/"},{"path":"/docs/handbook/nightly-builds.html"},{"path":"/docs/handbook/declaration-files/by-example.html"},{"path":"/docs/handbook/declaration-files/consumption.html"},{"path":"/docs/handbook/declaration-files/deep-dive.html"},{"path":"/docs/handbook/declaration-files/do-s-and-don-ts.html"},{"path":"/docs/handbook/declaration-files/introduction.html"},{"path":"/docs/handbook/declaration-files/library-structures.html"},{"path":"/docs/handbook/declaration-files/publishing.html"},{"path":"/docs/handbook/declaration-files/templates.html"},{"path":"/docs/handbook/typescript-in-5-minutes-func.html"},{"path":"/docs/handbook/typescript-in-5-minutes.html"},{"path":"/docs/handbook/typescript-in-5-minutes-oop.html"},{"path":"/docs/handbook/typescript-from-scratch.html"},{"path":"/docs/handbook/basic-types.html"},{"path":"/docs/handbook/classes.html"},{"path":"/docs/handbook/enums.html"},{"path":"/docs/handbook/functions.html"},{"path":"/docs/handbook/generics.html"},{"path":"/docs/handbook/interfaces.html"},{"path":"/docs/handbook/literal-types.html"},{"path":"/docs/handbook/intro.html"},{"path":"/docs/handbook/unions-and-intersections.html"},{"path":"/docs/handbook/declaration-files/dts-from-js.html"},{"path":"/docs/handbook/intro-to-js-ts.html"},{"path":"/docs/handbook/jsdoc-supported-types.html"},{"path":"/docs/handbook/type-checking-javascript-files.html"},{"path":"/docs/handbook/compiler-options-in-msbuild.html"},{"path":"/docs/handbook/compiler-options.html"},{"path":"/docs/handbook/configuring-watch.html"},{"path":"/docs/handbook/integrating-with-build-tools.html"},{"path":"/docs/handbook/project-references.html"},{"path":"/docs/handbook/tsconfig-json.html"},{"path":"/docs/handbook/advanced-types.html"},{"path":"/docs/handbook/declaration-merging.html"},{"path":"/docs/handbook/decorators.html"},{"path":"/docs/handbook/iterators-and-generators.html"},{"path":"/docs/handbook/jsx.html"},{"path":"/docs/handbook/mixins.html"},{"path":"/docs/handbook/module-resolution.html"},{"path":"/docs/handbook/modules.html"},{"path":"/docs/handbook/namespaces-and-modules.html"},{"path":"/docs/handbook/namespaces.html"},{"path":"/docs/handbook/symbols.html"},{"path":"/docs/handbook/triple-slash-directives.html"},{"path":"/docs/handbook/type-compatibility.html"},{"path":"/docs/handbook/type-inference.html"},{"path":"/docs/handbook/utility-types.html"},{"path":"/docs/handbook/variable-declarations.html"},{"path":"/docs/handbook/release-notes/typescript-1-1.html"},{"path":"/docs/handbook/release-notes/typescript-1-3.html"},{"path":"/docs/handbook/release-notes/typescript-1-4.html"},{"path":"/docs/handbook/release-notes/typescript-1-5.html"},{"path":"/docs/handbook/release-notes/typescript-1-6.html"},{"path":"/docs/handbook/release-notes/typescript-1-7.html"},{"path":"/docs/handbook/release-notes/typescript-1-8.html"},{"path":"/docs/handbook/release-notes/typescript-2-0.html"},{"path":"/docs/handbook/release-notes/typescript-2-1.html"},{"path":"/docs/handbook/release-notes/typescript-2-2.html"},{"path":"/docs/handbook/release-notes/typescript-2-3.html"},{"path":"/docs/handbook/release-notes/typescript-2-4.html"},{"path":"/docs/handbook/release-notes/typescript-2-5.html"},{"path":"/docs/handbook/release-notes/typescript-2-6.html"},{"path":"/docs/handbook/release-notes/typescript-2-7.html"},{"path":"/docs/handbook/release-notes/typescript-2-8.html"},{"path":"/docs/handbook/release-notes/typescript-2-9.html"},{"path":"/docs/handbook/release-notes/typescript-3-0.html"},{"path":"/docs/handbook/release-notes/typescript-3-1.html"},{"path":"/docs/handbook/release-notes/typescript-3-2.html"},{"path":"/docs/handbook/release-notes/typescript-3-3.html"},{"path":"/docs/handbook/release-notes/typescript-3-4.html"},{"path":"/docs/handbook/release-notes/typescript-3-5.html"},{"path":"/docs/handbook/release-notes/typescript-3-6.html"},{"path":"/docs/handbook/release-notes/typescript-3-7.html"},{"path":"/docs/handbook/release-notes/typescript-3-8.html"},{"path":"/docs/handbook/release-notes/typescript-3-9.html"},{"path":"/docs/handbook/asp-net-core.html"},{"path":"/docs/handbook/angular.html"},{"path":"/docs/handbook/babel-with-typescript.html"},{"path":"/docs/handbook/dom-manipulation.html"},{"path":"/docs/handbook/gulp.html"},{"path":"/docs/handbook/migrating-from-javascript.html"},{"path":"/docs/handbook/react.html"},{"path":"/docs/handbook/typescript-tooling-in-5-minutes.html"},{"path":"/vo/docs/handbook/basic-types.html"},{"path":"/docs/handbook/declaration-files/templates/global-modifying-module-d-ts.html"},{"path":"/docs/handbook/declaration-files/templates/global-plugin-d-ts.html"},{"path":"/docs/handbook/declaration-files/templates/global-d-ts.html"},{"path":"/docs/handbook/declaration-files/templates/module-class-d-ts.html"},{"path":"/docs/handbook/declaration-files/templates/module-function-d-ts.html"},{"path":"/docs/handbook/declaration-files/templates/module-plugin-d-ts.html"},{"path":"/docs/handbook/declaration-files/templates/module-d-ts.html"},{"path":"/docs/handbook/release-notes/overview.html"},{"path":"/tsconfig"},{"path":"/en/tsconfig"},{"path":"/vo/tsconfig"},{"path":"/ja/tsconfig"},{"path":"/pt/tsconfig"},{"path":"/play"},{"path":"/en/play"},{"path":"/es/play"},{"path":"/ja/play"},{"path":"/pt/play"},{"path":"/vo/play"},{"path":"/zh/play"},{"path":"/fa/play"},{"path":"/play/3-7/fixits/big-number-literals.ts"},{"path":"/play/3-7/fixits/const-to-let.ts"},{"path":"/play/3-7/fixits/infer-from-usage-changes.ts"},{"path":"/play/3-7/syntax-and-messaging/flattened-error-reporting.ts"},{"path":"/play/3-7/syntax-and-messaging/nullish-coalescing.ts"},{"path":"/play/3-7/syntax-and-messaging/optional-chaining.ts"},{"path":"/play/3-7/types-and-code-flow/assertion-functions.ts"},{"path":"/play/3-7/types-and-code-flow/recursive-type-references.ts"},{"path":"/play/3-7/types-and-code-flow/uncalled-function-checks.ts"},{"path":"/play/3-8/breaking-changes/checking-unions-with-index-signatures.ts"},{"path":"/play/3-8/jsdoc-improvements/accessibility-modifiers.js"},{"path":"/play/3-8/syntax-and-messaging/export-modules-from.ts"},{"path":"/play/3-8/syntax-and-messaging/private-class-fields.ts"},{"path":"/play/4-0/new-checks/class-constructor-code-flow.ts"},{"path":"/play/4-0/new-js-features/jsdoc-deprecated.ts"},{"path":"/play/4-0/new-js-features/logical-operators-and-assignment.ts"},{"path":"/play/4-0/new-js-features/nullish-coalescing.ts"},{"path":"/play/4-0/new-ts-features/named-tuples.ts"},{"path":"/play/4-0/new-ts-features/unknown-in-catch.ts"},{"path":"/play/4-0/new-ts-features/variadic-tuples.ts"},{"path":"/play/javascript/external-apis/typescript-with-deno.ts"},{"path":"/play/javascript/external-apis/typescript-with-node.js"},{"path":"/play/javascript/external-apis/typescript-with-web.js"},{"path":"/play/javascript/external-apis/typescript-with-webgl.js"},{"path":"/play/javascript/functions-with-javascript/function-chaining.ts"},{"path":"/play/javascript/functions-with-javascript/generic-functions.ts"},{"path":"/play/javascript/functions-with-javascript/typing-functions.ts"},{"path":"/play/javascript/helping-with-javascript/errors.ts"},{"path":"/play/javascript/helping-with-javascript/quick-fixes.ts"},{"path":"/play/javascript/javascript-essentials/code-flow.ts"},{"path":"/play/javascript/javascript-essentials/functions.ts"},{"path":"/play/javascript/javascript-essentials/hello-world.ts"},{"path":"/play/javascript/javascript-essentials/objects-and-arrays.ts"},{"path":"/play/javascript/modern-javascript/async-await.ts"},{"path":"/play/javascript/modern-javascript/immutability.ts"},{"path":"/play/javascript/modern-javascript/import-export.ts"},{"path":"/play/javascript/modern-javascript/jsdoc-support.js"},{"path":"/play/javascript/working-with-classes/classes-101.ts"},{"path":"/play/javascript/working-with-classes/generic-classes.ts"},{"path":"/play/javascript/working-with-classes/mixins.ts"},{"path":"/play/javascript/working-with-classes/this.ts"},{"path":"/play/playground/config/javascript-playgrounds.js"},{"path":"/play/playground/config/new-compiler-defaults.ts"},{"path":"/play/playground/language/automatic-type-acquisition.ts"},{"path":"/play/playground/language/fixits.ts"},{"path":"/play/playground/tooling/mobile-support.ts"},{"path":"/play/playground/tooling/sharable-urls.ts"},{"path":"/play/playground/tooling/typescript-versions.ts"},{"path":"/play/typescript/language/soundness.ts"},{"path":"/play/typescript/language/structural-typing.ts"},{"path":"/play/typescript/language/type-guards.ts"},{"path":"/play/typescript/language/type-widening-and-narrowing.ts"},{"path":"/play/typescript/language-extensions/enums.ts"},{"path":"/play/typescript/language-extensions/nominal-typing.ts"},{"path":"/play/typescript/language-extensions/types-vs-interfaces.ts"},{"path":"/play/typescript/meta-types/conditional-types.ts"},{"path":"/play/typescript/meta-types/discriminate-types.ts"},{"path":"/play/typescript/meta-types/indexed-types.ts"},{"path":"/play/typescript/meta-types/mapped-types.ts"},{"path":"/play/typescript/primitives/any.ts"},{"path":"/play/typescript/primitives/literals.ts"},{"path":"/play/typescript/primitives/union-and-intersection-types.ts"},{"path":"/play/typescript/primitives/unknown-and-never.ts"},{"path":"/play/typescript/type-primitives/built-in-utility-types.ts"},{"path":"/play/typescript/type-primitives/nullable-types.ts"},{"path":"/play/typescript/type-primitives/tuples.ts"},{"path":"/es/play/javascript/external-apis/typescript-with-deno.ts"},{"path":"/es/play/javascript/external-apis/typescript-with-node.js"},{"path":"/es/play/javascript/external-apis/typescript-with-web.js"},{"path":"/es/play/javascript/functions-with-javascript/function-chaining.ts"},{"path":"/es/play/javascript/functions-with-javascript/generic-functions.ts"},{"path":"/es/play/javascript/javascript-essentials/hello-world.ts"},{"path":"/es/play/javascript/javascript-essentials/objects-and-arrays.ts"},{"path":"/es/play/typescript/language/soundness.ts"},{"path":"/es/play/typescript/language/structural-typing.ts"},{"path":"/es/play/typescript/language/type-guards.ts"},{"path":"/es/play/typescript/language/type-widening-and-narrowing.ts"},{"path":"/es/play/typescript/meta-types/conditional-types.ts"},{"path":"/es/play/typescript/meta-types/discriminate-types.ts"},{"path":"/es/play/typescript/meta-types/indexed-types.ts"},{"path":"/es/play/typescript/meta-types/mapped-types.ts"},{"path":"/es/play/typescript/primitives/any.ts"},{"path":"/es/play/typescript/primitives/literals.ts"},{"path":"/es/play/typescript/primitives/union-and-intersection-types.ts"},{"path":"/es/play/typescript/primitives/unknown-and-never.ts"},{"path":"/es/play/typescript/type-primitives/built-in-utility-types.ts"},{"path":"/es/play/typescript/type-primitives/nullable-types.ts"},{"path":"/es/play/typescript/type-primitives/tuples.ts"},{"path":"/fa/play/javascript/javascript-essentials/hello-world.ts"},{"path":"/ja/play/3-7/fixits/big-number-literals.ts"},{"path":"/ja/play/3-7/syntax-and-messaging/nullish-coalescing.ts"},{"path":"/ja/play/3-7/syntax-and-messaging/optional-chaining.ts"},{"path":"/ja/play/3-8/breaking-changes/checking-unions-with-index-signatures.ts"},{"path":"/ja/play/javascript/external-apis/typescript-with-deno.ts"},{"path":"/ja/play/typescript/language-extensions/enums.ts"},{"path":"/ja/play/typescript/language-extensions/nominal-typing.ts"},{"path":"/ja/play/typescript/language-extensions/types-vs-interfaces.ts"},{"path":"/ja/play/typescript/primitives/any.ts"},{"path":"/ja/play/typescript/primitives/literals.ts"},{"path":"/ja/play/typescript/primitives/union-and-intersection-types.ts"},{"path":"/ja/play/typescript/primitives/unknown-and-never.ts"},{"path":"/ja/play/typescript/type-primitives/built-in-utility-types.ts"},{"path":"/ja/play/typescript/type-primitives/nullable-types.ts"},{"path":"/ja/play/typescript/type-primitives/tuples.ts"},{"path":"/pt/play/javascript/javascript-essentials/code-flow.ts"},{"path":"/pt/play/javascript/javascript-essentials/functions.ts"},{"path":"/pt/play/javascript/javascript-essentials/hello-world.ts"},{"path":"/pt/play/javascript/javascript-essentials/objects-and-arrays.ts"},{"path":"/vo/play/javascript/javascript-essentials/code-flow.ts"},{"path":"/vo/play/javascript/javascript-essentials/functions.ts"},{"path":"/vo/play/javascript/javascript-essentials/hello-world.ts"},{"path":"/vo/play/javascript/javascript-essentials/objects-and-arrays.ts"},{"path":"/zh/play/javascript/external-apis/typescript-with-deno.ts"},{"path":"/zh/play/javascript/external-apis/typescript-with-node.js"},{"path":"/zh/play/javascript/external-apis/typescript-with-web.js"},{"path":"/zh/play/javascript/external-apis/typescript-with-webgl.js"},{"path":"/zh/play/javascript/functions-with-javascript/function-chaining.ts"},{"path":"/zh/play/javascript/functions-with-javascript/generic-functions.ts"},{"path":"/zh/play/javascript/functions-with-javascript/typing-functions.ts"},{"path":"/zh/play/javascript/helping-with-javascript/errors.ts"},{"path":"/zh/play/javascript/helping-with-javascript/quick-fixes.ts"},{"path":"/zh/play/javascript/javascript-essentials/code-flow.ts"},{"path":"/zh/play/javascript/javascript-essentials/functions.ts"},{"path":"/zh/play/javascript/javascript-essentials/hello-world.ts"},{"path":"/zh/play/javascript/javascript-essentials/objects-and-arrays.ts"},{"path":"/zh/play/javascript/modern-javascript/async-await.ts"},{"path":"/zh/play/javascript/modern-javascript/immutability.ts"},{"path":"/zh/play/javascript/modern-javascript/import-export.ts"},{"path":"/zh/play/javascript/modern-javascript/jsdoc-support.js"},{"path":"/zh/play/javascript/working-with-classes/classes-101.ts"},{"path":"/zh/play/javascript/working-with-classes/generic-classes.ts"},{"path":"/zh/play/javascript/working-with-classes/mixins.ts"},{"path":"/zh/play/javascript/working-with-classes/this.ts"},{"path":"/zh/play/playground/config/javascript-playgrounds.js"},{"path":"/zh/play/playground/config/new-compiler-defaults.ts"},{"path":"/zh/play/playground/language/automatic-type-acquisition.ts"},{"path":"/zh/play/playground/language/fixits.ts"},{"path":"/zh/play/playground/tooling/mobile-support.ts"},{"path":"/zh/play/playground/tooling/sharable-urls.ts"},{"path":"/zh/play/playground/tooling/typescript-versions.ts"},{"path":"/zh/play/typescript/language/soundness.ts"},{"path":"/zh/play/typescript/language/structural-typing.ts"},{"path":"/zh/play/typescript/language/type-guards.ts"},{"path":"/zh/play/typescript/language/type-widening-and-narrowing.ts"},{"path":"/zh/play/typescript/language-extensions/enums.ts"},{"path":"/zh/play/typescript/language-extensions/nominal-typing.ts"},{"path":"/zh/play/typescript/language-extensions/types-vs-interfaces.ts"},{"path":"/zh/play/typescript/meta-types/conditional-types.ts"},{"path":"/zh/play/typescript/meta-types/discriminate-types.ts"},{"path":"/zh/play/typescript/meta-types/indexed-types.ts"},{"path":"/zh/play/typescript/meta-types/mapped-types.ts"},{"path":"/zh/play/typescript/primitives/any.ts"},{"path":"/zh/play/typescript/primitives/literals.ts"},{"path":"/zh/play/typescript/primitives/union-and-intersection-types.ts"},{"path":"/zh/play/typescript/primitives/unknown-and-never.ts"},{"path":"/zh/play/typescript/type-primitives/built-in-utility-types.ts"},{"path":"/zh/play/typescript/type-primitives/nullable-types.ts"},{"path":"/zh/play/typescript/type-primitives/tuples.ts"},{"path":"/ja/play/3-7/syntax-and-messaging/flattened-error-reporting.ts"},{"path":"/ja/play/3-7/fixits/infer-from-usage-changes.ts"},{"path":"/ja/play/3-7/fixits/const-to-let.ts"},{"path":"/community"},{"path":"/es/community"},{"path":"/ja/community"},{"path":"/vo/community"},{"path":"/zh/community"},{"path":"/download"},{"path":"/es/download"},{"path":"/ja/download"},{"path":"/vo/download"},{"path":"/zh/download"},{"path":"/empty"},{"path":"/es/empty"},{"path":"/ja/empty"},{"path":"/vo/empty"},{"path":"/zh/empty"},{"path":"/"},{"path":"/es/"},{"path":"/ja/"},{"path":"/vo/"},{"path":"/zh/"},{"path":"/tools"},{"path":"/es/tools"},{"path":"/ja/tools"},{"path":"/vo/tools"},{"path":"/zh/tools"},{"path":"/why-create-typescript"},{"path":"/es/why-create-typescript"},{"path":"/ja/why-create-typescript"},{"path":"/vo/why-create-typescript"},{"path":"/zh/why-create-typescript"},{"path":"/docs/bootstrap"},{"path":"/es/docs/bootstrap"},{"path":"/ja/docs/bootstrap"},{"path":"/vo/docs/bootstrap"},{"path":"/zh/docs/bootstrap"},{"path":"/docs/"},{"path":"/es/docs/"},{"path":"/ja/docs/"},{"path":"/vo/docs/"},{"path":"/zh/docs/"},{"path":"/docs/handbook/"},{"path":"/es/docs/handbook/"},{"path":"/ja/docs/handbook/"},{"path":"/vo/docs/handbook/"},{"path":"/zh/docs/handbook/"},{"path":"/branding/"},{"path":"/dev/bug-workbench/"},{"path":"/dev/playground-plugins/"},{"path":"/dev/sandbox/"},{"path":"/dev/twoslash/"},{"path":"/dev/typescript-vfs/"},{"path":"/upcoming/"}]},"markdownRemark":{"id":"cda52721-4b39-5ef6-8bf0-508bf5e3a79f","excerpt":"Improvements in Inference and Promise.all Recent versions of TypeScript (around 3.7) have had updates to the declarations of functions like Promise.all and…","html":"<h2 id=\"improvements-in-inference-and-promiseall\" style=\"position:relative;\"><a href=\"#improvements-in-inference-and-promiseall\" aria-label=\"improvements in inference and promiseall permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Improvements in Inference and <code>Promise.all</code></h2>\n<p>Recent versions of TypeScript (around 3.7) have had updates to the declarations of functions like <code>Promise.all</code> and <code>Promise.race</code>.\nUnfortunately, that introduced a few regressions, especially when mixing in values with <code>null</code> or <code>undefined</code>.</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">interface</span><span style=\"color: #000000\"> Lion {</span>\n<span style=\"color: #000000\">  roar(): void;</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">interface</span><span style=\"color: #000000\"> Seal {</span>\n<span style=\"color: #000000\">  singKissFromARose(): void;</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">async</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> visitZoo(</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">lionExhibit</span><span style=\"color: #000000\">: Promise&lt;Lion&gt;,</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">sealExhibit</span><span style=\"color: #000000\">: Promise&lt;Seal | undefined&gt;</span>\n<span style=\"color: #000000\">) {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> [</span><span style=\"color: #1A1A1A\">lion</span><span style=\"color: #000000\">, </span><span style=\"color: #1A1A1A\">seal</span><span style=\"color: #000000\">] = </span><span style=\"color: #0000FF\">await</span><span style=\"color: #000000\"> Promise.all([</span><span style=\"color: #1A1A1A\">lionExhibit</span><span style=\"color: #000000\">, </span><span style=\"color: #1A1A1A\">sealExhibit</span><span style=\"color: #000000\">]);</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">lion</span><span style=\"color: #000000\">.roar(); </span><span style=\"color: #008000\">// uh oh</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #008000\">//  ~~~~</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #008000\">// Object is possibly 'undefined'.</span>\n<span style=\"color: #000000\">}</span></code></div></pre>\n<p>This is strange behavior!\nThe fact that <code>sealExhibit</code> contained an <code>undefined</code> somehow poisoned type of <code>lion</code> to include <code>undefined</code>.</p>\n<p>Thanks to <a href=\"https://github.com/microsoft/TypeScript/pull/34501\">a pull request</a> from <a href=\"https://github.com/jablko\">Jack Bates</a>, this has been fixed with improvements in our inference process in TypeScript 3.9.\nThe above no longer errors.\nIf you’ve been stuck on older versions of TypeScript due to issues around <code>Promise</code>s, we encourage you to give 3.9 a shot!</p>\n<h3 id=\"what-about-the-awaited-type\" style=\"position:relative;\"><a href=\"#what-about-the-awaited-type\" aria-label=\"what about the awaited type permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What About the <code>awaited</code> Type?</h3>\n<p>If you’ve been following our issue tracker and design meeting notes, you might be aware of some work around <a href=\"https://github.com/microsoft/TypeScript/pull/35998\">a new type operator called <code>awaited</code></a>.\nThis goal of this type operator is to accurately model the way that <code>Promise</code> unwrapping works in JavaScript.</p>\n<p>We initially anticipated shipping <code>awaited</code> 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.\nAs a result, we’ve decided to pull the feature out of our main branch until we feel more confident.\nWe’ll be experimenting more with the feature, but we won’t be shipping it as part of this release.</p>\n<h2 id=\"speed-improvements\" style=\"position:relative;\"><a href=\"#speed-improvements\" aria-label=\"speed improvements permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Speed Improvements</h2>\n<p>TypeScript 3.9 ships with many new speed improvements.\nOur team has been focusing on performance after observing extremely poor editing/compilation speed with packages like material-ui and styled-components.\nWe’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.</p>\n<ul>\n<li><a href=\"https://github.com/microsoft/TypeScript/pull/36576\">https://github.com/microsoft/TypeScript/pull/36576</a></li>\n<li><a href=\"https://github.com/microsoft/TypeScript/pull/36590\">https://github.com/microsoft/TypeScript/pull/36590</a></li>\n<li><a href=\"https://github.com/microsoft/TypeScript/pull/36607\">https://github.com/microsoft/TypeScript/pull/36607</a></li>\n<li><a href=\"https://github.com/microsoft/TypeScript/pull/36622\">https://github.com/microsoft/TypeScript/pull/36622</a></li>\n<li><a href=\"https://github.com/microsoft/TypeScript/pull/36754\">https://github.com/microsoft/TypeScript/pull/36754</a></li>\n<li><a href=\"https://github.com/microsoft/TypeScript/pull/36696\">https://github.com/microsoft/TypeScript/pull/36696</a></li>\n</ul>\n<p>Each of these pull requests gains about a 5-10% reduction in compile times on certain codebases.\nIn total, we believe we’ve achieved around a 40% reduction in material-ui’s compile time!</p>\n<p>We also have some changes to file renaming functionality in editor scenarios.\nWe 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.\nTypeScript 3.9 addresses this issue by <a href=\"https://github.com/microsoft/TypeScript/pull/37055\">changing the internals of how the compiler and language service caches file lookups</a>.</p>\n<p>While there’s still room for improvement, we hope this work translates to a snappier experience for everyone!</p>\n<h2 id=\"-ts-expect-error-comments\" style=\"position:relative;\"><a href=\"#-ts-expect-error-comments\" aria-label=\" ts expect error comments permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><code>// @ts-expect-error</code> Comments</h2>\n<p>Imagine that we’re writing a library in TypeScript and we’re exporting some function called <code>doStuff</code> as part of our public API.\nThe function’s types declare that it takes two <code>string</code>s so that other TypeScript users can get type-checking errors, but it also does a runtime check (maybe only in development builds) to give JavaScript users a helpful error.</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> doStuff(</span><span style=\"color: #1A1A1A\">abc</span><span style=\"color: #000000\">: string, </span><span style=\"color: #1A1A1A\">xyz</span><span style=\"color: #000000\">: string) {</span>\n<span style=\"color: #000000\">  assert(</span><span style=\"color: #0000FF\">typeof</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">abc</span><span style=\"color: #000000\"> === </span><span style=\"color: #A31515\">\"string\"</span><span style=\"color: #000000\">);</span>\n<span style=\"color: #000000\">  assert(</span><span style=\"color: #0000FF\">typeof</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">xyz</span><span style=\"color: #000000\"> === </span><span style=\"color: #A31515\">\"string\"</span><span style=\"color: #000000\">);</span>\n\n<span style=\"color: #000000\">  </span><span style=\"color: #008000\">// do some stuff</span>\n<span style=\"color: #000000\">}</span></code></div></pre>\n<p>So TypeScript users will get a helpful red squiggle and an error message when they misuse this function, and JavaScript users will get an assertion error.\nWe’d like to test this behavior, so we’ll write a unit test.</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #000000\">expect(() </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> {</span>\n<span style=\"color: #000000\">  doStuff(</span><span style=\"color: #09835A\">123</span><span style=\"color: #000000\">, </span><span style=\"color: #09835A\">456</span><span style=\"color: #000000\">);</span>\n<span style=\"color: #000000\">}).toThrow();</span></code></div></pre>\n<p>Unfortunately if our tests are written in TypeScript, TypeScript will give us an error!</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #000000\">doStuff(</span><span style=\"color: #09835A\">123</span><span style=\"color: #000000\">, </span><span style=\"color: #09835A\">456</span><span style=\"color: #000000\">);</span>\n<span style=\"color: #008000\">//          ~~~</span>\n<span style=\"color: #008000\">// error: Type 'number' is not assignable to type 'string'.</span></code></div></pre>\n<p>That’s why TypeScript 3.9 brings a new feature: <code>// @ts-expect-error</code> comments.\nWhen a line is prefixed with a <code>// @ts-expect-error</code> comment, TypeScript will suppress that error from being reported;\nbut if there’s no error, TypeScript will report that <code>// @ts-expect-error</code> wasn’t necessary.</p>\n<p>As a quick example, the following code is okay</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #008000\">// @ts-expect-error</span>\n<span style=\"color: #000000\">console.log(</span><span style=\"color: #09835A\">47</span><span style=\"color: #000000\"> * </span><span style=\"color: #A31515\">\"octopus\"</span><span style=\"color: #000000\">);</span></code></div></pre>\n<p>while the following code</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #008000\">// @ts-expect-error</span>\n<span style=\"color: #000000\">console.log(</span><span style=\"color: #09835A\">1</span><span style=\"color: #000000\"> + </span><span style=\"color: #09835A\">1</span><span style=\"color: #000000\">);</span></code></div></pre>\n<p>results in the error</p>\n<pre><code>Unused '@ts-expect-error' directive.\n</code></pre>\n<p>We’d like to extend a big thanks to <a href=\"https://github.com/JoshuaKGoldberg\">Josh Goldberg</a>, the contributor who implemented this feature.\nFor more information, you can take a look at <a href=\"https://github.com/microsoft/TypeScript/pull/36014\">the <code>ts-expect-error</code> pull request</a>.</p>\n<h3 id=\"ts-ignore-or-ts-expect-error\" style=\"position:relative;\"><a href=\"#ts-ignore-or-ts-expect-error\" aria-label=\"ts ignore or ts expect error permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><code>ts-ignore</code> or <code>ts-expect-error</code>?</h3>\n<p>In some ways <code>// @ts-expect-error</code> can act as a suppression comment, similar to <code>// @ts-ignore</code>.\nThe difference is that <code>// @ts-ignore</code> will do nothing if the following line is error-free.</p>\n<p>You might be tempted to switch existing <code>// @ts-ignore</code> comments over to <code>// @ts-expect-error</code>, and you might be wondering which is appropriate for future code.\nWhile it’s entirely up to you and your team, we have some ideas of which to pick in certain situations.</p>\n<p>Pick <code>ts-expect-error</code> if:</p>\n<ul>\n<li>you’re writing test code where you actually want the type system to error on an operation</li>\n<li>you expect a fix to be coming in fairly quickly and you just need a quick workaround</li>\n<li>you’re in a reasonably-sized project with a proactive team that wants to remove suppression comments as soon affected code is valid again</li>\n</ul>\n<p>Pick <code>ts-ignore</code> if:</p>\n<ul>\n<li>you have an a larger project and and new errors have appeared in code with no clear owner</li>\n<li>you are in the middle of an upgrade between two different versions of TypeScript, and a line of code errors in one version but not another.</li>\n<li>you honestly don’t have the time to decide which of these options is better.</li>\n</ul>\n<h2 id=\"uncalled-function-checks-in-conditional-expressions\" style=\"position:relative;\"><a href=\"#uncalled-function-checks-in-conditional-expressions\" aria-label=\"uncalled function checks in conditional expressions permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Uncalled Function Checks in Conditional Expressions</h2>\n<p>In TypeScript 3.7 we introduced <em>uncalled function checks</em> to report an error when you’ve forgotten to call a function.</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> hasImportantPermissions(): boolean {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #008000\">// ...</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #008000\">// Oops!</span>\n<span style=\"color: #0000FF\">if</span><span style=\"color: #000000\"> (</span><span style=\"color: #1A1A1A\">hasImportantPermissions</span><span style=\"color: #000000\">) {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #008000\">//  ~~~~~~~~~~~~~~~~~~~~~~~</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #008000\">// This condition will always return true since the function is always defined.</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #008000\">// Did you mean to call it instead?</span>\n<span style=\"color: #000000\">  deleteAllTheImportantFiles();</span>\n<span style=\"color: #000000\">}</span></code></div></pre>\n<p>However, this error only applied to conditions in <code>if</code> statements.\nThanks to <a href=\"https://github.com/microsoft/TypeScript/pull/36402\">a pull request</a> from <a href=\"https://github.com/a-tarasyuk\">Alexander Tarasyuk</a>, this feature is also now supported in ternary conditionals (i.e. the <code>cond ? trueExpr : falseExpr</code> syntax).</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">declare</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> listFilesOfDirectory(</span><span style=\"color: #1A1A1A\">dirPath</span><span style=\"color: #000000\">: string): string[];</span>\n<span style=\"color: #0000FF\">declare</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> isDirectory(): boolean;</span>\n\n<span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> getAllFiles(</span><span style=\"color: #1A1A1A\">startFileName</span><span style=\"color: #000000\">: string) {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">const</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">result</span><span style=\"color: #000000\">:</span><span style=\"color: #1A1A1A\"> string[] </span><span style=\"color: #000000\">= [];</span>\n<span style=\"color: #000000\">  traverse(</span><span style=\"color: #1A1A1A\">startFileName</span><span style=\"color: #000000\">);</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">result</span><span style=\"color: #000000\">;</span>\n\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> traverse(</span><span style=\"color: #1A1A1A\">currentPath</span><span style=\"color: #000000\">: string) {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">isDirectory</span>\n<span style=\"color: #000000\">      ? </span><span style=\"color: #008000\">//     ~~~~~~~~~~~</span>\n<span style=\"color: #000000\">        </span><span style=\"color: #008000\">// This condition will always return true</span>\n<span style=\"color: #000000\">        </span><span style=\"color: #008000\">// since the function is always defined.</span>\n<span style=\"color: #000000\">        </span><span style=\"color: #008000\">// Did you mean to call it instead?</span>\n<span style=\"color: #000000\">        listFilesOfDirectory(</span><span style=\"color: #1A1A1A\">currentPath</span><span style=\"color: #000000\">).forEach(</span><span style=\"color: #1A1A1A\">traverse</span><span style=\"color: #000000\">)</span>\n<span style=\"color: #000000\">      : </span><span style=\"color: #1A1A1A\">result</span><span style=\"color: #000000\">.push(</span><span style=\"color: #1A1A1A\">currentPath</span><span style=\"color: #000000\">);</span>\n<span style=\"color: #000000\">  }</span>\n<span style=\"color: #000000\">}</span></code></div></pre>\n<p><a href=\"https://github.com/microsoft/TypeScript/issues/36048\">https://github.com/microsoft/TypeScript/issues/36048</a></p>\n<h2 id=\"editor-improvements\" style=\"position:relative;\"><a href=\"#editor-improvements\" aria-label=\"editor improvements permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Editor Improvements</h2>\n<p>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.\nUsing new TypeScript/JavaScript functionality in your editor will differ depending on your editor, but</p>\n<ul>\n<li>Visual Studio Code supports <a href=\"https://code.visualstudio.com/docs/typescript/typescript-compiling#_using-the-workspace-version-of-typescript\">selecting different versions of TypeScript</a>. Alternatively, there’s the <a href=\"https://marketplace.visualstudio.com/items?itemName=ms-vscode.vscode-typescript-next\">JavaScript/TypeScript Nightly Extension</a> to stay on the bleeding edge (which is typically very stable).</li>\n<li>Visual Studio 2017/2019 have [the SDK installers above] and <a href=\"https://www.nuget.org/packages/Microsoft.TypeScript.MSBuild\">MSBuild installs</a>.</li>\n<li>Sublime Text 3 supports <a href=\"https://github.com/microsoft/TypeScript-Sublime-Plugin#note-using-different-versions-of-typescript\">selecting different versions of TypeScript</a></li>\n</ul>\n<h3 id=\"commonjs-auto-imports-in-javascript\" style=\"position:relative;\"><a href=\"#commonjs-auto-imports-in-javascript\" aria-label=\"commonjs auto imports in javascript permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>CommonJS Auto-Imports in JavaScript</h3>\n<p>One great new improvement is in auto-imports in JavaScript files using CommonJS modules.</p>\n<p>In older versions, TypeScript always assumed that regardless of your file, you wanted an ECMAScript-style import like</p>\n<pre class=\"shiki\"><div class=\"language-id\">js</div><div class='code-container'><code><span style=\"color: #0000FF\">import</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">*</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">as</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">fs</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">from</span><span style=\"color: #000000\"> </span><span style=\"color: #A31515\">\"fs\"</span><span style=\"color: #000000\">;</span></code></div></pre>\n<p>However, not everyone is targeting ECMAScript-style modules when writing JavaScript files.\nPlenty of users still use CommonJS-style <code>require(...)</code> imports like so</p>\n<pre class=\"shiki\"><div class=\"language-id\">js</div><div class='code-container'><code><span style=\"color: #0000FF\">const</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">fs</span><span style=\"color: #000000\"> = require(</span><span style=\"color: #A31515\">\"fs\"</span><span style=\"color: #000000\">);</span></code></div></pre>\n<p>TypeScript now automatically detects the types of imports you’re using to keep your file’s style clean and consistent.</p>\n<p><video src=\"https://devblogs.microsoft.com/typescript/wp-content/uploads/sites/11/2020/03/ERkaliGU0AA5anJ1.mp4\"></video></p>\n<p>For more details on the change, see <a href=\"https://github.com/microsoft/TypeScript/pull/37027\">the corresponding pull request</a>.</p>\n<h3 id=\"code-actions-preserve-newlines\" style=\"position:relative;\"><a href=\"#code-actions-preserve-newlines\" aria-label=\"code actions preserve newlines permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Code Actions Preserve Newlines</h3>\n<p>TypeScript’s refactorings and quick fixes often didn’t do a great job of preserving newlines.\nAs a really basic example, take the following code.</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">const</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">maxValue </span><span style=\"color: #000000\">= </span><span style=\"color: #09835A\">100</span><span style=\"color: #000000\">;</span>\n\n<span style=\"color: #008000\">/*start*/</span>\n<span style=\"color: #0000FF\">for</span><span style=\"color: #000000\"> (</span><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">i </span><span style=\"color: #000000\">= </span><span style=\"color: #09835A\">0</span><span style=\"color: #000000\">; </span><span style=\"color: #1A1A1A\">i</span><span style=\"color: #000000\"> &lt;= </span><span style=\"color: #1A1A1A\">maxValue</span><span style=\"color: #000000\">; </span><span style=\"color: #1A1A1A\">i</span><span style=\"color: #000000\">++) {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #008000\">// First get the squared value.</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">square </span><span style=\"color: #000000\">= </span><span style=\"color: #1A1A1A\">i</span><span style=\"color: #000000\"> ** </span><span style=\"color: #09835A\">2</span><span style=\"color: #000000\">;</span>\n\n<span style=\"color: #000000\">  </span><span style=\"color: #008000\">// Now print the squared value.</span>\n<span style=\"color: #000000\">  console.log(</span><span style=\"color: #1A1A1A\">square</span><span style=\"color: #000000\">);</span>\n<span style=\"color: #000000\">}</span>\n<span style=\"color: #008000\">/*end*/</span></code></div></pre>\n<p>If we highlighted the range from <code>/*start*/</code> to <code>/*end*/</code> in our editor to extract to a new function, we’d end up with code like the following.</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">const</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">maxValue </span><span style=\"color: #000000\">= </span><span style=\"color: #09835A\">100</span><span style=\"color: #000000\">;</span>\n\n<span style=\"color: #000000\">printSquares();</span>\n\n<span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> printSquares() {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">for</span><span style=\"color: #000000\"> (</span><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">i </span><span style=\"color: #000000\">= </span><span style=\"color: #09835A\">0</span><span style=\"color: #000000\">; </span><span style=\"color: #1A1A1A\">i</span><span style=\"color: #000000\"> &lt;= </span><span style=\"color: #1A1A1A\">maxValue</span><span style=\"color: #000000\">; </span><span style=\"color: #1A1A1A\">i</span><span style=\"color: #000000\">++) {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #008000\">// First get the squared value.</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">square </span><span style=\"color: #000000\">= </span><span style=\"color: #1A1A1A\">i</span><span style=\"color: #000000\"> ** </span><span style=\"color: #09835A\">2</span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #008000\">// Now print the squared value.</span>\n<span style=\"color: #000000\">    console.log(</span><span style=\"color: #1A1A1A\">square</span><span style=\"color: #000000\">);</span>\n<span style=\"color: #000000\">  }</span>\n<span style=\"color: #000000\">}</span></code></div></pre>\n<p><img src=\"https://devblogs.microsoft.com/typescript/wp-content/uploads/sites/11/2020/03/printSquaresWithoutNewlines-3.9.gif.gif\" alt=\"Extracting the for loop to a function in older versions of TypeScript. A newline is not preserved.\"></p>\n<p>That’s not ideal - we had a blank line between each statement in our <code>for</code> loop, but the refactoring got rid of it!\nTypeScript 3.9 does a little more work to preserve what we write.</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">const</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">maxValue </span><span style=\"color: #000000\">= </span><span style=\"color: #09835A\">100</span><span style=\"color: #000000\">;</span>\n\n<span style=\"color: #000000\">printSquares();</span>\n\n<span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> printSquares() {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">for</span><span style=\"color: #000000\"> (</span><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">i </span><span style=\"color: #000000\">= </span><span style=\"color: #09835A\">0</span><span style=\"color: #000000\">; </span><span style=\"color: #1A1A1A\">i</span><span style=\"color: #000000\"> &lt;= </span><span style=\"color: #1A1A1A\">maxValue</span><span style=\"color: #000000\">; </span><span style=\"color: #1A1A1A\">i</span><span style=\"color: #000000\">++) {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #008000\">// First get the squared value.</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">square </span><span style=\"color: #000000\">= </span><span style=\"color: #1A1A1A\">i</span><span style=\"color: #000000\"> ** </span><span style=\"color: #09835A\">2</span><span style=\"color: #000000\">;</span>\n\n<span style=\"color: #000000\">    </span><span style=\"color: #008000\">// Now print the squared value.</span>\n<span style=\"color: #000000\">    console.log(</span><span style=\"color: #1A1A1A\">square</span><span style=\"color: #000000\">);</span>\n<span style=\"color: #000000\">  }</span>\n<span style=\"color: #000000\">}</span></code></div></pre>\n<p><img src=\"https://devblogs.microsoft.com/typescript/wp-content/uploads/sites/11/2020/03/printSquaresWithNewlines-3.9.gif.gif\" alt=\"Extracting the for loop to a function in TypeScript 3.9. A newline is preserved.\"></p>\n<p>You can see more about the implementation <a href=\"https://github.com/microsoft/TypeScript/pull/36688\">in this pull request</a></p>\n<h3 id=\"quick-fixes-for-missing-return-expressions\" style=\"position:relative;\"><a href=\"#quick-fixes-for-missing-return-expressions\" aria-label=\"quick fixes for missing return expressions permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Quick Fixes for Missing Return Expressions</h3>\n<p>There are occasions where we might forget to return the value of the last statement in a function, especially when adding curly braces to arrow functions.</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #008000\">// before</span>\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">f1 </span><span style=\"color: #000000\">= () </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> </span><span style=\"color: #09835A\">42</span><span style=\"color: #000000\">;</span>\n\n<span style=\"color: #008000\">// oops - not the same!</span>\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">f2 </span><span style=\"color: #000000\">= () </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #09835A\">42</span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">};</span></code></div></pre>\n<p>Thanks to <a href=\"https://github.com/microsoft/TypeScript/pull/26434\">a pull request</a> from community member <a href=\"https://github.com/Kingwl\">Wenlu Wang</a>, TypeScript can provide a quick-fix to add missing <code>return</code> statements, remove curly braces, or add parentheses to arrow function bodies that look suspiciously like object literals.</p>\n<p><img src=\"https://devblogs.microsoft.com/typescript/wp-content/uploads/sites/11/2020/04/missingReturnValue-3-9.gif\" alt=\"TypeScript fixing an error where no expression is returned by adding a &#x60;return&#x60; statement or removing curly braces.\"></p>\n<h3 id=\"support-for-solution-style-tsconfigjson-files\" style=\"position:relative;\"><a href=\"#support-for-solution-style-tsconfigjson-files\" aria-label=\"support for solution style tsconfigjson files permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Support for “Solution Style” <code>tsconfig.json</code> Files</h3>\n<p>Editors need to figure out which configuration file a file belongs to so that it can apply the appropriate options and figure out which other files are included in the current “project”.\nBy default, editors powered by TypeScript’s language server do this by walking up each parent directory to find a <code>tsconfig.json</code>.</p>\n<p>One case where this slightly fell over is when a <code>tsconfig.json</code> simply existed to reference other <code>tsconfig.json</code> files.</p>\n<pre class=\"shiki\"><div class=\"language-id\">json</div><div class='code-container'><code><span style=\"color: #008000\">// tsconfig.json</span>\n<span style=\"color: #000000\">{</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #AF0B08\">files</span><span style=\"color: #000000\">: [],</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #AF0B08\">references</span><span style=\"color: #000000\">: [</span>\n<span style=\"color: #000000\">    { </span><span style=\"color: #AF0B08\">path</span><span style=\"color: #000000\">: </span><span style=\"color: #A31515\">\"./tsconfig.shared.json\"</span><span style=\"color: #000000\"> },</span>\n<span style=\"color: #000000\">    { </span><span style=\"color: #AF0B08\">path</span><span style=\"color: #000000\">: </span><span style=\"color: #A31515\">\"./tsconfig.frontend.json\"</span><span style=\"color: #000000\"> },</span>\n<span style=\"color: #000000\">    { </span><span style=\"color: #AF0B08\">path</span><span style=\"color: #000000\">: </span><span style=\"color: #A31515\">\"./tsconfig.backend.json\"</span><span style=\"color: #000000\"> },</span>\n<span style=\"color: #000000\">  ],</span>\n<span style=\"color: #000000\">}</span></code></div></pre>\n<p>This file that really does nothing but manage other project files is often called a “solution” in some environments.\nHere, none of these <code>tsconfig.*.json</code> files get picked up by the server, but we’d really like the language server to understand that the current <code>.ts</code> file probably belongs to one of the mentioned projects in this root <code>tsconfig.json</code>.</p>\n<p>TypeScript 3.9 adds support to editing scenarios for this configuration.\nFor more details, take a look at <a href=\"https://github.com/microsoft/TypeScript/pull/37239\">the pull request that added this functionality</a>.</p>\n<h2 id=\"breaking-changes\" style=\"position:relative;\"><a href=\"#breaking-changes\" aria-label=\"breaking changes permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Breaking Changes</h2>\n<h3 id=\"parsing-differences-in-optional-chaining-and-non-null-assertions\" style=\"position:relative;\"><a href=\"#parsing-differences-in-optional-chaining-and-non-null-assertions\" aria-label=\"parsing differences in optional chaining and non null assertions permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Parsing Differences in Optional Chaining and Non-Null Assertions</h3>\n<p>TypeScript recently implemented the optional chaining operator, but we’ve received user feedback that the behavior of optional chaining (<code>?.</code>) with the non-null assertion operator (<code>!</code>) is extremely counter-intuitive.</p>\n<p>Specifically, in previous versions, the code</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #1A1A1A\">foo</span><span style=\"color: #000000\">?.</span><span style=\"color: #1A1A1A\">bar</span><span style=\"color: #000000\">!.</span><span style=\"color: #1A1A1A\">baz</span><span style=\"color: #000000\">;</span></code></div></pre>\n<p>was interpreted to be equivalent to the following JavaScript.</p>\n<pre class=\"shiki\"><div class=\"language-id\">js</div><div class='code-container'><code><span style=\"color: #000000\">(</span><span style=\"color: #1A1A1A\">foo</span><span style=\"color: #000000\">?.</span><span style=\"color: #1A1A1A\">bar</span><span style=\"color: #000000\">).</span><span style=\"color: #1A1A1A\">baz</span><span style=\"color: #000000\">;</span></code></div></pre>\n<p>In the above code the parentheses stop the “short-circuiting” behavior of optional chaining, so if <code>foo</code> is <code>undefined</code>, accessing <code>baz</code> will cause a runtime error.</p>\n<p>The Babel team who pointed this behavior out, and most users who provided feedback to us, believe that this behavior is wrong.\nWe do too!\nThe thing we heard the most was that the <code>!</code> operator should just “disappear” since the intent was to remove <code>null</code> and <code>undefined</code> from the type of <code>bar</code>.</p>\n<p>In other words, most people felt that the original snippet should be interpreted as</p>\n<pre class=\"shiki\"><div class=\"language-id\">js</div><div class='code-container'><code><span style=\"color: #1A1A1A\">foo</span><span style=\"color: #000000\">?.</span><span style=\"color: #1A1A1A\">bar</span><span style=\"color: #000000\">.</span><span style=\"color: #1A1A1A\">baz</span><span style=\"color: #000000\">;</span></code></div></pre>\n<p>which just evaluates to <code>undefined</code> when <code>foo</code> is <code>undefined</code>.</p>\n<p>This is a breaking change, but we believe most code was written with the new interpretation in mind.\nUsers who want to revert to the old behavior can add explicit parentheses around the left side of the <code>!</code> operator.</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #1A1A1A\">foo</span><span style=\"color: #000000\">?.</span><span style=\"color: #1A1A1A\">bar</span><span style=\"color: #000000\">!.</span><span style=\"color: #1A1A1A\">baz</span><span style=\"color: #000000\">;</span></code></div></pre>\n<h3 id=\"-and--are-now-invalid-jsx-text-characters\" style=\"position:relative;\"><a href=\"#-and--are-now-invalid-jsx-text-characters\" aria-label=\" and  are now invalid jsx text characters permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><code>}</code> and <code>></code> are Now Invalid JSX Text Characters</h3>\n<p>The JSX Specification forbids the use of the <code>}</code> and <code>></code> characters in text positions.\nTypeScript and Babel have both decided to enforce this rule to be more comformant.\nThe new way to insert these characters is to use an HTML escape code (e.g. <code>&#x3C;span> 2 &#x26;gt 1 &#x3C;/div></code>) or insert an expression with a string literal (e.g. <code>&#x3C;span> 2 {\">\"} 1 &#x3C;/div></code>).</p>\n<p>Luckily, thanks to the <a href=\"https://github.com/microsoft/TypeScript/pull/36636\">pull request</a> enforcing this from <a href=\"https://github.com/bradzacher\">Brad Zacher</a>, you’ll get an error message along the lines of</p>\n<pre><code>Unexpected token. Did you mean `{'>'}` or `&#x26;gt;`?\nUnexpected token. Did you mean `{'}'}` or `&#x26;rbrace;`?\n</code></pre>\n<p>For example:</p>\n<pre class=\"shiki\"><div class=\"language-id\">tsx</div><div class='code-container'><code><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">directions</span><span style=\"color: #000000\"> = </span><span style=\"color: #800000\">&lt;span&gt;</span><span style=\"color: #000000\">Navigate to: Menu Bar &gt; Tools &gt; Options</span><span style=\"color: #800000\">&lt;/div&gt;</span>\n<span style=\"color: #008000\">//                                           ~       ~</span>\n<span style=\"color: #008000\">// Unexpected token. Did you mean `{'&gt;'}` or `&gt;`?</span></code></div></pre>\n<p>That error message came with a handy quick fix, and thanks to <a href=\"https://github.com/a-tarasyuk\">Alexander Tarasyuk</a>, <a href=\"https://github.com/microsoft/TypeScript/pull/37436\">you can apply these changes in bulk</a> if you have a lot of errors.</p>\n<h3 id=\"stricter-checks-on-intersections-and-optional-properties\" style=\"position:relative;\"><a href=\"#stricter-checks-on-intersections-and-optional-properties\" aria-label=\"stricter checks on intersections and optional properties permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Stricter Checks on Intersections and Optional Properties</h3>\n<p>Generally, an intersection type like <code>A &#x26; B</code> is assignable to <code>C</code> if either <code>A</code> or <code>B</code> is assignable to <code>C</code>; however, sometimes that has problems with optional properties.\nFor example, take the following:</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">interface</span><span style=\"color: #000000\"> A {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">a</span><span style=\"color: #000000\">: number; </span><span style=\"color: #008000\">// notice this is 'number'</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">interface</span><span style=\"color: #000000\"> B {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">b</span><span style=\"color: #000000\">: string;</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">interface</span><span style=\"color: #000000\"> C {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">a</span><span style=\"color: #000000\">?: boolean; </span><span style=\"color: #008000\">// notice this is 'boolean'</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">b</span><span style=\"color: #000000\">: string;</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">declare</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">x</span><span style=\"color: #000000\">:</span><span style=\"color: #1A1A1A\"> A </span><span style=\"color: #000000\">&</span><span style=\"color: #1A1A1A\"> B</span><span style=\"color: #000000\">;</span>\n<span style=\"color: #0000FF\">declare</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">y</span><span style=\"color: #000000\">:</span><span style=\"color: #1A1A1A\"> C</span><span style=\"color: #000000\">;</span>\n\n<span style=\"color: #1A1A1A\">y</span><span style=\"color: #000000\"> = </span><span style=\"color: #1A1A1A\">x</span><span style=\"color: #000000\">;</span></code></div></pre>\n<p>In previous versions of TypeScript, this was allowed because while <code>A</code> was totally incompatible with <code>C</code>, <code>B</code> <em>was</em> compatible with <code>C</code>.</p>\n<p>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.\nAs a result, TypeScript will see that the <code>a</code> property of <code>A &#x26; B</code> is incompatible with that of <code>C</code>:</p>\n<pre><code>Type 'A &#x26; B' is not assignable to type 'C'.\n  Types of property 'a' are incompatible.\n    Type 'number' is not assignable to type 'boolean | undefined'.\n</code></pre>\n<p>For more information on this change, <a href=\"https://github.com/microsoft/TypeScript/pull/37195\">see the corresponding pull request</a>.</p>\n<h3 id=\"intersections-reduced-by-discriminant-properties\" style=\"position:relative;\"><a href=\"#intersections-reduced-by-discriminant-properties\" aria-label=\"intersections reduced by discriminant properties permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Intersections Reduced By Discriminant Properties</h3>\n<p>There are a few cases where you might end up with types that describe values that just don’t exist.\nFor example</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">declare</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> smushObjects&lt;T, U&gt;(</span><span style=\"color: #1A1A1A\">x</span><span style=\"color: #000000\">: T, </span><span style=\"color: #1A1A1A\">y</span><span style=\"color: #000000\">: U): T & U;</span>\n\n<span style=\"color: #0000FF\">interface</span><span style=\"color: #000000\"> Circle {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">kind</span><span style=\"color: #000000\">: </span><span style=\"color: #A31515\">\"circle\"</span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">radius</span><span style=\"color: #000000\">: number;</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">interface</span><span style=\"color: #000000\"> Square {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">kind</span><span style=\"color: #000000\">: </span><span style=\"color: #A31515\">\"square\"</span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">sideLength</span><span style=\"color: #000000\">: number;</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">declare</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">x</span><span style=\"color: #000000\">:</span><span style=\"color: #1A1A1A\"> Circle</span><span style=\"color: #000000\">;</span>\n<span style=\"color: #0000FF\">declare</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">y</span><span style=\"color: #000000\">:</span><span style=\"color: #1A1A1A\"> Square</span><span style=\"color: #000000\">;</span>\n\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">z </span><span style=\"color: #000000\">= smushObjects(</span><span style=\"color: #1A1A1A\">x</span><span style=\"color: #000000\">, </span><span style=\"color: #1A1A1A\">y</span><span style=\"color: #000000\">);</span>\n<span style=\"color: #000000\">console.log(</span><span style=\"color: #1A1A1A\">z</span><span style=\"color: #000000\">.</span><span style=\"color: #1A1A1A\">kind</span><span style=\"color: #000000\">);</span></code></div></pre>\n<p>This code is slightly weird because there’s really no way to create an intersection of a <code>Circle</code> and a <code>Square</code> - they have two incompatible <code>kind</code> fields.\nIn previous versions of TypeScript, this code was allowed and the type of <code>kind</code> itself was <code>never</code> because <code>\"circle\" &#x26; \"square\"</code> described a set of values that could <code>never</code> exist.</p>\n<p>In TypeScript 3.9, the type system is more aggressive here - it notices that it’s impossible to intersect <code>Circle</code> and <code>Square</code> because of their <code>kind</code> properties.\nSo instead of collapsing the type of <code>z.kind</code> to <code>never</code>, it collapses the type of <code>z</code> itself (<code>Circle &#x26; Square</code>) to <code>never</code>.\nThat means the above code now errors with:</p>\n<pre><code>Property 'kind' does not exist on type 'never'.\n</code></pre>\n<p>Most of the breaks we observed seem to correspond with slightly incorrect type declarations.\nFor more details, <a href=\"https://github.com/microsoft/TypeScript/pull/36696\">see the original pull request</a>.</p>\n<h3 id=\"getterssetters-are-no-longer-enumerable\" style=\"position:relative;\"><a href=\"#getterssetters-are-no-longer-enumerable\" aria-label=\"getterssetters are no longer enumerable permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Getters/Setters are No Longer Enumerable</h3>\n<p>In older versions of TypeScript, <code>get</code> and <code>set</code> accessors 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.\nAs a result, TypeScript code that targeted ES5 and ES2015 could differ in behavior.</p>\n<p>Thanks to <a href=\"https://github.com/microsoft/TypeScript/pull/32264\">a pull request</a> from GitHub user <a href=\"https://github.com/pathurs\">pathurs</a>, TypeScript 3.9 now conforms more closely with ECMAScript in this regard.</p>\n<h3 id=\"type-parameters-that-extend-any-no-longer-act-as-any\" style=\"position:relative;\"><a href=\"#type-parameters-that-extend-any-no-longer-act-as-any\" aria-label=\"type parameters that extend any no longer act as any permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Type Parameters That Extend <code>any</code> No Longer Act as <code>any</code></h3>\n<p>In previous versions of TypeScript, a type parameter constrained to <code>any</code> could be treated as <code>any</code>.</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> foo&lt;T </span><span style=\"color: #0000FF\">extends</span><span style=\"color: #000000\"> any&gt;(</span><span style=\"color: #1A1A1A\">arg</span><span style=\"color: #000000\">: T) {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">arg</span><span style=\"color: #000000\">.</span><span style=\"color: #1A1A1A\">spfjgerijghoied</span><span style=\"color: #000000\">; </span><span style=\"color: #008000\">// no error!</span>\n<span style=\"color: #000000\">}</span></code></div></pre>\n<p>This was an oversight, so TypeScript 3.9 takes a more conservative approach and issues an error on these questionable operations.</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> foo&lt;T </span><span style=\"color: #0000FF\">extends</span><span style=\"color: #000000\"> any&gt;(</span><span style=\"color: #1A1A1A\">arg</span><span style=\"color: #000000\">: T) {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">arg</span><span style=\"color: #000000\">.</span><span style=\"color: #1A1A1A\">spfjgerijghoied</span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #008000\">//  ~~~~~~~~~~~~~~~</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #008000\">// Property 'spfjgerijghoied' does not exist on type 'T'.</span>\n<span style=\"color: #000000\">}</span></code></div></pre>\n<h3 id=\"export--is-always-retained\" style=\"position:relative;\"><a href=\"#export--is-always-retained\" aria-label=\"export  is always retained permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><code>export *</code> is Always Retained</h3>\n<p>In previous TypeScript versions, declarations like <code>export * from \"foo\"</code> would be dropped in our JavaScript output if <code>foo</code> didn’t export any values.\nThis sort of emit is problematic because it’s type-directed and can’t be emulated by Babel.\nTypeScript 3.9 will always emit these <code>export *</code> declarations.\nIn practice, we don’t expect this to break much existing code.</p>\n<h3 id=\"more-libdomdts-refinements\" style=\"position:relative;\"><a href=\"#more-libdomdts-refinements\" aria-label=\"more libdomdts refinements permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>More libdom.d.ts refinements</h3>\n<p>We are continuing to move more of TypeScript’s built-in .d.ts library (lib.d.ts and family) to be generated from Web IDL files directly from the DOM specification.\nAs a result some vendor-specific types related to media access have been removed.</p>\n<p>Adding this file to an ambient <code>*.d.ts</code> to your project will bring them back:</p>\n<!-- prettier-ignore -->\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">interface</span><span style=\"color: #000000\"> AudioTrackList {</span>\n<span style=\"color: #000000\">     [Symbol.</span><span style=\"color: #1A1A1A\">iterator</span><span style=\"color: #000000\">](): IterableIterator&lt;AudioTrack&gt;;</span>\n<span style=\"color: #000000\"> }</span>\n\n<span style=\"color: #0000FF\">interface</span><span style=\"color: #000000\"> HTMLVideoElement {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">readonly</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">audioTracks</span><span style=\"color: #000000\">: AudioTrackList</span>\n\n<span style=\"color: #000000\">  msFrameStep(</span><span style=\"color: #1A1A1A\">forward</span><span style=\"color: #000000\">: boolean): void;</span>\n<span style=\"color: #000000\">  msInsertVideoEffect(</span><span style=\"color: #1A1A1A\">activatableClassId</span><span style=\"color: #000000\">: string, </span><span style=\"color: #1A1A1A\">effectRequired</span><span style=\"color: #000000\">: boolean, </span><span style=\"color: #1A1A1A\">config</span><span style=\"color: #000000\">?: any): void;</span>\n<span style=\"color: #000000\">  msSetVideoRectangle(</span><span style=\"color: #1A1A1A\">left</span><span style=\"color: #000000\">: number, </span><span style=\"color: #1A1A1A\">top</span><span style=\"color: #000000\">: number, </span><span style=\"color: #1A1A1A\">right</span><span style=\"color: #000000\">: number, </span><span style=\"color: #1A1A1A\">bottom</span><span style=\"color: #000000\">: number): void;</span>\n<span style=\"color: #000000\">  webkitEnterFullScreen(): void;</span>\n<span style=\"color: #000000\">  webkitEnterFullscreen(): void;</span>\n<span style=\"color: #000000\">  webkitExitFullScreen(): void;</span>\n<span style=\"color: #000000\">  webkitExitFullscreen(): void;</span>\n\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">msHorizontalMirror</span><span style=\"color: #000000\">: boolean;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">readonly</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">msIsLayoutOptimalForPlayback</span><span style=\"color: #000000\">: boolean;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">readonly</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">msIsStereo3D</span><span style=\"color: #000000\">: boolean;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">msStereo3DPackingMode</span><span style=\"color: #000000\">: string;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">msStereo3DRenderMode</span><span style=\"color: #000000\">: string;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">msZoom</span><span style=\"color: #000000\">: boolean;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">onMSVideoFormatChanged</span><span style=\"color: #000000\">: ((</span><span style=\"color: #1A1A1A\">this</span><span style=\"color: #000000\">: HTMLVideoElement, </span><span style=\"color: #1A1A1A\">ev</span><span style=\"color: #000000\">: Event) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> any) | null;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">onMSVideoFrameStepCompleted</span><span style=\"color: #000000\">: ((</span><span style=\"color: #1A1A1A\">this</span><span style=\"color: #000000\">: HTMLVideoElement, </span><span style=\"color: #1A1A1A\">ev</span><span style=\"color: #000000\">: Event) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> any) | null;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">onMSVideoOptimalLayoutChanged</span><span style=\"color: #000000\">: ((</span><span style=\"color: #1A1A1A\">this</span><span style=\"color: #000000\">: HTMLVideoElement, </span><span style=\"color: #1A1A1A\">ev</span><span style=\"color: #000000\">: Event) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> any) | null;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">webkitDisplayingFullscreen</span><span style=\"color: #000000\">: boolean;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">webkitSupportsFullscreen</span><span style=\"color: #000000\">: boolean;</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">interface</span><span style=\"color: #000000\"> MediaError {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">readonly</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">msExtendedCode</span><span style=\"color: #000000\">: number;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">readonly</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">MS_MEDIA_ERR_ENCRYPTED</span><span style=\"color: #000000\">: number;</span>\n<span style=\"color: #000000\">}</span></code></div></pre>","headings":[{"value":"Improvements in Inference and Promise.all","depth":2},{"value":"What About the awaited Type?","depth":3},{"value":"Speed Improvements","depth":2},{"value":"// @ts-expect-error Comments","depth":2},{"value":"ts-ignore or ts-expect-error?","depth":3},{"value":"Uncalled Function Checks in Conditional Expressions","depth":2},{"value":"Editor Improvements","depth":2},{"value":"CommonJS Auto-Imports in JavaScript","depth":3},{"value":"Code Actions Preserve Newlines","depth":3},{"value":"Quick Fixes for Missing Return Expressions","depth":3},{"value":"Support for “Solution Style” tsconfig.json Files","depth":3},{"value":"Breaking Changes","depth":2},{"value":"Parsing Differences in Optional Chaining and Non-Null Assertions","depth":3},{"value":"} and > are Now Invalid JSX Text Characters","depth":3},{"value":"Stricter Checks on Intersections and Optional Properties","depth":3},{"value":"Intersections Reduced By Discriminant Properties","depth":3},{"value":"Getters/Setters are No Longer Enumerable","depth":3},{"value":"Type Parameters That Extend any No Longer Act as any","depth":3},{"value":"export * is Always Retained","depth":3},{"value":"More libdom.d.ts refinements","depth":3}],"frontmatter":{"permalink":"/docs/handbook/release-notes/typescript-3-9.html","title":"TypeScript 3.9","disable_toc":null,"oneline":"TypeScript 3.9 Release Notes"}},"prev":null,"next":null},"pageContext":{"id":"typescript-3.9","slug":"/docs/handbook/release-notes/typescript-3-9.html","repoPath":"/packages/documentation/copy/en/release-notes/TypeScript 3.9.md","lang":"en","modifiedTime":"2020-08-07T17:00:36.347Z"}}}