{"componentChunkName":"component---src-templates-handbook-tsx","path":"/docs/handbook/release-notes/typescript-3-4.html","result":{"data":{"allSitePage":{"nodes":[{"path":"/dev-404-page/"},{"path":"/docs/handbook/advanced-types.html"},{"path":"/docs/handbook/basic-types.html"},{"path":"/docs/handbook/classes.html"},{"path":"/docs/handbook/compiler-options-in-msbuild.html"},{"path":"/docs/handbook/compiler-options.html"},{"path":"/docs/handbook/configuring-watch.html"},{"path":"/docs/handbook/declaration-merging.html"},{"path":"/docs/handbook/decorators.html"},{"path":"/docs/handbook/enums.html"},{"path":"/docs/handbook/functions.html"},{"path":"/docs/handbook/generics.html"},{"path":"/docs/handbook/integrating-with-build-tools.html"},{"path":"/docs/handbook/interfaces.html"},{"path":"/docs/handbook/iterators-and-generators.html"},{"path":"/docs/handbook/jsdoc-supported-types.html"},{"path":"/docs/handbook/jsx.html"},{"path":"/docs/handbook/literal-types.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/nightly-builds.html"},{"path":"/docs/handbook/project-references.html"},{"path":"/docs/handbook/symbols.html"},{"path":"/docs/handbook/"},{"path":"/docs/handbook/triple-slash-directives.html"},{"path":"/docs/handbook/type-checking-javascript-files.html"},{"path":"/docs/handbook/type-compatibility.html"},{"path":"/docs/handbook/type-inference.html"},{"path":"/docs/handbook/unions-and-intersections.html"},{"path":"/docs/handbook/utility-types.html"},{"path":"/docs/handbook/variable-declarations.html"},{"path":"/docs/handbook/writing-declaration-files.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/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-2.html"},{"path":"/docs/handbook/release-notes/typescript-2-1.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/asp-net-core.html"},{"path":"/docs/handbook/angular.html"},{"path":"/docs/handbook/dom-manipulation.html"},{"path":"/docs/handbook/gulp.html"},{"path":"/docs/handbook/migrating-from-javascript.html"},{"path":"/docs/handbook/react-&-webpack.html"},{"path":"/docs/handbook/react.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/typescript-tooling-in-5-minutes.html"},{"path":"/docs/handbook/tsconfig-json.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":"/ja/tsconfig"},{"path":"/vo/tsconfig"},{"path":"/play"},{"path":"/en/play"},{"path":"/es/play"},{"path":"/vo/play"},{"path":"/zh/play"},{"path":"/ja/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/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/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":"/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/type-primitives/built-in-utility-types.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/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":"/zh/play/javascript/modern-javascript/immutability.ts"},{"path":"/zh/play/javascript/modern-javascript/async-await.ts"},{"path":"/zh/play/javascript/javascript-essentials/objects-and-arrays.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/home"},{"path":"/es/docs/home"},{"path":"/ja/docs/home"},{"path":"/vo/docs/home"},{"path":"/zh/docs/home"},{"path":"/dev/playground-plugins/"},{"path":"/dev/sandbox/"},{"path":"/dev/twoslash/"},{"path":"/dev/typescript-vfs/"}]},"markdownRemark":{"id":"7c593368-c6c2-574c-844e-191f75a88cfd","excerpt":"Faster subsequent builds with the --incremental flag TypeScript 3.4 introduces a new flag called --incremental which tells TypeScript to save information about…","html":"<h2 id=\"faster-subsequent-builds-with-the---incremental-flag\" style=\"position:relative;\"><a href=\"#faster-subsequent-builds-with-the---incremental-flag\" aria-label=\"faster subsequent builds with the   incremental flag 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>Faster subsequent builds with the <code>--incremental</code> flag</h2>\n<p>TypeScript 3.4 introduces a new flag called <code>--incremental</code> which tells TypeScript to save information about the project graph from the last compilation.\nThe next time TypeScript is invoked with <code>--incremental</code>, it will use that information to detect the least costly way to type-check and emit changes to your project.</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: #0451A5\">\"compilerOptions\"</span><span style=\"color: #000000\">: {</span>\n<span style=\"color: #000000\">        </span><span style=\"color: #0451A5\">\"incremental\"</span><span style=\"color: #000000\">: </span><span style=\"color: #0000FF\">true</span><span style=\"color: #000000\">,</span>\n<span style=\"color: #000000\">        </span><span style=\"color: #0451A5\">\"outDir\"</span><span style=\"color: #000000\">: </span><span style=\"color: #A31515\">\"./lib\"</span>\n<span style=\"color: #000000\">    },</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0451A5\">\"include\"</span><span style=\"color: #000000\">: [</span><span style=\"color: #A31515\">\"./src\"</span><span style=\"color: #000000\">]</span>\n<span style=\"color: #000000\">}</span></code></div></pre>\n<p>By default with these settings, when we run <code>tsc</code>, TypeScript will look for a file called <code>.tsbuildinfo</code> in the output directory (<code>./lib</code>).\nIf <code>./lib/.tsbuildinfo</code> doesn’t exist, it’ll be generated.\nBut if it does, <code>tsc</code> will try to use that file to incrementally type-check and update our output files.</p>\n<p>These <code>.tsbuildinfo</code> files can be safely deleted and don’t have any impact on our code at runtime - they’re purely used to make compilations faster.\nWe can also name them anything that we want, and place them anywhere we want using the <code>--tsBuildInfoFile</code> flag.</p>\n<pre class=\"shiki\"><div class=\"language-id\">json</div><div class='code-container'><code><span style=\"color: #008000\">// front-end.tsconfig.json</span>\n<span style=\"color: #000000\">{</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0451A5\">\"compilerOptions\"</span><span style=\"color: #000000\">: {</span>\n<span style=\"color: #000000\">        </span><span style=\"color: #0451A5\">\"incremental\"</span><span style=\"color: #000000\">: </span><span style=\"color: #0000FF\">true</span><span style=\"color: #000000\">,</span>\n<span style=\"color: #000000\">        </span><span style=\"color: #0451A5\">\"tsBuildInfoFile\"</span><span style=\"color: #000000\">: </span><span style=\"color: #A31515\">\"./buildcache/front-end\"</span><span style=\"color: #000000\">,</span>\n<span style=\"color: #000000\">        </span><span style=\"color: #0451A5\">\"outDir\"</span><span style=\"color: #000000\">: </span><span style=\"color: #A31515\">\"./lib\"</span>\n<span style=\"color: #000000\">    },</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0451A5\">\"include\"</span><span style=\"color: #000000\">: [</span><span style=\"color: #A31515\">\"./src\"</span><span style=\"color: #000000\">]</span>\n<span style=\"color: #000000\">}</span></code></div></pre>\n<h3 id=\"composite-projects\" style=\"position:relative;\"><a href=\"#composite-projects\" aria-label=\"composite projects 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>Composite projects</h3>\n<p>Part of the intent with composite projects (<code>tsconfig.json</code>s with <code>composite</code> set to <code>true</code>) is that references between different projects can be built incrementally.\nAs such, composite projects will <strong>always</strong> produce <code>.tsbuildinfo</code> files.</p>\n<h3 id=\"outfile\" style=\"position:relative;\"><a href=\"#outfile\" aria-label=\"outfile 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>outFile</code></h3>\n<p>When <code>outFile</code> is used, the build information file’s name will be based on the output file’s name.\nAs an example, if our output JavaScript file is <code>./output/foo.js</code>, then under the <code>--incremental</code> flag, TypeScript will generate the file <code>./output/foo.tsbuildinfo</code>.\nAs above, this can be controlled with the <code>--tsBuildInfoFile</code> flag.</p>\n<h2 id=\"higher-order-type-inference-from-generic-functions\" style=\"position:relative;\"><a href=\"#higher-order-type-inference-from-generic-functions\" aria-label=\"higher order type inference from generic functions 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>Higher order type inference from generic functions</h2>\n<p>TypeScript 3.4 can now produce generic function types when inference from other generic functions produces free type variables for inferences.\nThis means many function composition patterns now work better in 3.4.</p>\n<p>To get more specific, let’s build up some motivation and consider the following <code>compose</code> 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\"> compose&lt;A, B, C&gt;(f: (arg: A) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> B, g: (arg: B) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> C): (arg: A) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> C {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> x </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> g(f(x));</span>\n<span style=\"color: #000000\">}</span></code></div></pre>\n<p><code>compose</code> takes two other functions:</p>\n<ul>\n<li><code>f</code> which takes some argument (of type <code>A</code>) and returns a value of type <code>B</code></li>\n<li><code>g</code> which takes an argument of type <code>B</code> (the type <code>f</code> returned), and returns a value of type <code>C</code></li>\n</ul>\n<p><code>compose</code> then returns a function which feeds its argument through <code>f</code> and then <code>g</code>.</p>\n<p>When calling this function, TypeScript will try to figure out the types of <code>A</code>, <code>B</code>, and <code>C</code> through a process called <em>type argument inference</em>.\nThis inference process usually works pretty well:</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\"> Person {</span>\n<span style=\"color: #000000\">    name: string;</span>\n<span style=\"color: #000000\">    age: number;</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> getDisplayName(p: Person) {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> p.name.toLowerCase();</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> getLength(s: string) {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> s.length;</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #008000\">// has type '(p: Person) =&gt; number'</span>\n<span style=\"color: #0000FF\">const</span><span style=\"color: #000000\"> getDisplayNameLength = compose(</span>\n<span style=\"color: #000000\">    getDisplayName,</span>\n<span style=\"color: #000000\">    getLength,</span>\n<span style=\"color: #000000\">);</span>\n\n<span style=\"color: #008000\">// works and returns the type 'number'</span>\n<span style=\"color: #000000\">getDisplayNameLength({ name: </span><span style=\"color: #A31515\">\"Person McPersonface\"</span><span style=\"color: #000000\">, age: </span><span style=\"color: #09835A\">42</span><span style=\"color: #000000\"> });</span></code></div></pre>\n<p>The inference process is fairly straightforward here because <code>getDisplayName</code> and <code>getLength</code> use types that can easily be referenced.\nHowever, in TypeScript 3.3 and earlier, generic functions like <code>compose</code> didn’t work so well when passed other generic functions.</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\"> Box&lt;T&gt; {</span>\n<span style=\"color: #000000\">    value: T;</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> makeArray&lt;T&gt;(x: T): T[] {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> [x];</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> makeBox&lt;U&gt;(value: U): Box&lt;U&gt; {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> { value };</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #008000\">// has type '(arg: {}) =&gt; Box&lt;{}[]&gt;'</span>\n<span style=\"color: #0000FF\">const</span><span style=\"color: #000000\"> makeBoxedArray = compose(</span>\n<span style=\"color: #000000\">    makeArray,</span>\n<span style=\"color: #000000\">    makeBox,</span>\n<span style=\"color: #000000\">)</span>\n\n<span style=\"color: #000000\">makeBoxedArray(</span><span style=\"color: #A31515\">\"hello!\"</span><span style=\"color: #000000\">).value[</span><span style=\"color: #09835A\">0</span><span style=\"color: #000000\">].toUpperCase();</span>\n<span style=\"color: #008000\">//                                ~~~~~~~~~~~</span>\n<span style=\"color: #008000\">// error: Property 'toUpperCase' does not exist on type '{}'.</span></code></div></pre>\n<p>In older versions, TypeScript would infer the empty object type (<code>{}</code>) when inferring from other type variables like <code>T</code> and <code>U</code>.</p>\n<p>During type argument inference in TypeScript 3.4, for a call to a generic function that returns a function type, TypeScript <em>will</em>, as appropriate, propagate type parameters from generic function arguments onto the resulting function type.</p>\n<p>In other words, instead of producing the type</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #000000\">(arg: {}) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> Box&lt;{}[]&gt;</span></code></div></pre>\n<p>TypeScript 3.4 produces the type</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #000000\">&lt;T&gt;(arg: T) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> Box&lt;T[]&gt;</span></code></div></pre>\n<p>Notice that <code>T</code> has been propagated from <code>makeArray</code> into the resulting type’s type parameter list.\nThis means that genericity from <code>compose</code>’s arguments has been preserved and our <code>makeBoxedArray</code> sample will just work!</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\"> Box&lt;T&gt; {</span>\n<span style=\"color: #000000\">    value: T;</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> makeArray&lt;T&gt;(x: T): T[] {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> [x];</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> makeBox&lt;U&gt;(value: U): Box&lt;U&gt; {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> { value };</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #008000\">// has type '&lt;T&gt;(arg: T) =&gt; Box&lt;T[]&gt;'</span>\n<span style=\"color: #0000FF\">const</span><span style=\"color: #000000\"> makeBoxedArray = compose(</span>\n<span style=\"color: #000000\">    makeArray,</span>\n<span style=\"color: #000000\">    makeBox,</span>\n<span style=\"color: #000000\">)</span>\n\n<span style=\"color: #008000\">// works with no problem!</span>\n<span style=\"color: #000000\">makeBoxedArray(</span><span style=\"color: #A31515\">\"hello!\"</span><span style=\"color: #000000\">).value[</span><span style=\"color: #09835A\">0</span><span style=\"color: #000000\">].toUpperCase();</span></code></div></pre>\n<p>For more details, you can <a href=\"https://github.com/Microsoft/TypeScript/pull/30215\">read more at the original change</a>.</p>\n<h2 id=\"improvements-for-readonlyarray-and-readonly-tuples\" style=\"position:relative;\"><a href=\"#improvements-for-readonlyarray-and-readonly-tuples\" aria-label=\"improvements for readonlyarray and readonly tuples 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 for <code>ReadonlyArray</code> and <code>readonly</code> tuples</h2>\n<p>TypeScript 3.4 makes it a little bit easier to use read-only array-like types.</p>\n<h3 id=\"a-new-syntax-for-readonlyarray\" style=\"position:relative;\"><a href=\"#a-new-syntax-for-readonlyarray\" aria-label=\"a new syntax for readonlyarray 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>A new syntax for <code>ReadonlyArray</code></h3>\n<p>The <code>ReadonlyArray</code> type describes <code>Array</code>s that can only be read from.\nAny variable with a reference to a <code>ReadonlyArray</code> can’t add, remove, or replace any elements of the array.</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(arr: ReadonlyArray&lt;string&gt;) {</span>\n<span style=\"color: #000000\">    arr.slice();        </span><span style=\"color: #008000\">// okay</span>\n<span style=\"color: #000000\">    arr.push(</span><span style=\"color: #A31515\">\"hello!\"</span><span style=\"color: #000000\">); </span><span style=\"color: #008000\">// error!</span>\n<span style=\"color: #000000\">}</span></code></div></pre>\n<p>While it’s good practice to use <code>ReadonlyArray</code> over <code>Array</code> when no mutation is intended, it’s often been a pain given that arrays have a nicer syntax.\nSpecifically, <code>number[]</code> is a shorthand version of <code>Array&#x3C;number></code>, just as <code>Date[]</code> is a shorthand for <code>Array&#x3C;Date></code>.</p>\n<p>TypeScript 3.4 introduces a new syntax for <code>ReadonlyArray</code> using a new <code>readonly</code> modifier for array types.</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(arr: readonly string[]) {</span>\n<span style=\"color: #000000\">    arr.slice();        </span><span style=\"color: #008000\">// okay</span>\n<span style=\"color: #000000\">    arr.push(</span><span style=\"color: #A31515\">\"hello!\"</span><span style=\"color: #000000\">); </span><span style=\"color: #008000\">// error!</span>\n<span style=\"color: #000000\">}</span></code></div></pre>\n<h3 id=\"readonly-tuples\" style=\"position:relative;\"><a href=\"#readonly-tuples\" aria-label=\"readonly tuples 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>readonly</code> tuples</h3>\n<p>TypeScript 3.4 also introduces new support for <code>readonly</code> tuples.\nWe can prefix any tuple type with the <code>readonly</code> keyword to make it a <code>readonly</code> tuple, much like we now can with array shorthand syntax.\nAs you might expect, unlike ordinary tuples whose slots could be written to, <code>readonly</code> tuples only permit reading from those positions.</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(pair: readonly [string, string]) {</span>\n<span style=\"color: #000000\">    console.log(pair[</span><span style=\"color: #09835A\">0</span><span style=\"color: #000000\">]);   </span><span style=\"color: #008000\">// okay</span>\n<span style=\"color: #000000\">    pair[</span><span style=\"color: #09835A\">1</span><span style=\"color: #000000\">] = </span><span style=\"color: #A31515\">\"hello!\"</span><span style=\"color: #000000\">;     </span><span style=\"color: #008000\">// error</span>\n<span style=\"color: #000000\">}</span></code></div></pre>\n<p>The same way that ordinary tuples are types that extend from <code>Array</code> - a tuple with elements of type <code>T<sub>1</sub></code>, <code>T<sub>2</sub></code>, … <code>T<sub>n</sub></code> extends from <code>Array&#x3C; T<sub>1</sub> | T<sub>2</sub> | … T<sub>n</sub> ></code> - <code>readonly</code> tuples are types that extend from <code>ReadonlyArray</code>. So a <code>readonly</code> tuple with elements <code>T<sub>1</sub></code>, <code>T<sub>2</sub></code>, … <code>T<sub>n</sub></code> extends from <code>ReadonlyArray&#x3C; T<sub>1</sub> | T<sub>2</sub> | … T<sub>n</sub> ></code>.</p>\n<h3 id=\"readonly-mapped-type-modifiers-and-readonly-arrays\" style=\"position:relative;\"><a href=\"#readonly-mapped-type-modifiers-and-readonly-arrays\" aria-label=\"readonly mapped type modifiers and readonly arrays 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>readonly</code> mapped type modifiers and <code>readonly</code> arrays</h3>\n<p>In earlier versions of TypeScript, we generalized mapped types to operate differently on array-like types.\nThis meant that a mapped type like <code>Boxify</code> could work on arrays and tuples alike.</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\"> Box&lt;T&gt; { value: T }</span>\n\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> Boxify&lt;T&gt; = {</span>\n<span style=\"color: #000000\">    [K </span><span style=\"color: #0000FF\">in</span><span style=\"color: #000000\"> keyof T]: Box&lt;T[K]&gt;</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #008000\">// { a: Box&lt;string&gt;, b: Box&lt;number&gt; }</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> A = Boxify&lt;{ a: string, b: number }&gt;;</span>\n\n<span style=\"color: #008000\">// Array&lt;Box&lt;number&gt;&gt;</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> B = Boxify&lt;number[]&gt;;</span>\n\n<span style=\"color: #008000\">// [Box&lt;string&gt;, Box&lt;number&gt;]</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> C = Boxify&lt;[string, boolean]&gt;;</span></code></div></pre>\n<p>Unfortunately, mapped types like the <code>Readonly</code> utility type were effectively no-ops on array and tuple types.</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #008000\">// lib.d.ts</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> Readonly&lt;T&gt; = {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">readonly</span><span style=\"color: #000000\"> [K </span><span style=\"color: #0000FF\">in</span><span style=\"color: #000000\"> keyof T]: T[K]</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #008000\">// How code acted *before* TypeScript 3.4</span>\n\n<span style=\"color: #008000\">// { readonly a: string, readonly b: number }</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> A = Readonly&lt;{ a: string, b: number }&gt;;</span>\n\n<span style=\"color: #008000\">// number[]</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> B = Readonly&lt;number[]&gt;;</span>\n\n<span style=\"color: #008000\">// [string, boolean]</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> C = Readonly&lt;[string, boolean]&gt;;</span></code></div></pre>\n<p>In TypeScript 3.4, the <code>readonly</code> modifier in a mapped type will automatically convert array-like types to their corresponding <code>readonly</code> counterparts.</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #008000\">// How code acts now *with* TypeScript 3.4</span>\n\n<span style=\"color: #008000\">// { readonly a: string, readonly b: number }</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> A = Readonly&lt;{ a: string, b: number }&gt;;</span>\n\n<span style=\"color: #008000\">// readonly number[]</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> B = Readonly&lt;number[]&gt;;</span>\n\n<span style=\"color: #008000\">// readonly [string, boolean]</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> C = Readonly&lt;[string, boolean]&gt;;</span></code></div></pre>\n<p>Similarly, you could write a utility type like <code>Writable</code> mapped type that strips away <code>readonly</code>-ness, and that would convert <code>readonly</code> array containers back to their mutable equivalents.</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> Writable&lt;T&gt; = {</span>\n<span style=\"color: #000000\">    -</span><span style=\"color: #0000FF\">readonly</span><span style=\"color: #000000\"> [K </span><span style=\"color: #0000FF\">in</span><span style=\"color: #000000\"> keyof T]: T[K]</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #008000\">// { a: string, b: number }</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> A = Writable&lt;{</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">readonly</span><span style=\"color: #000000\"> a: string;</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">readonly</span><span style=\"color: #000000\"> b: number</span>\n<span style=\"color: #000000\">}&gt;;</span>\n\n<span style=\"color: #008000\">// number[]</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> B = Writable&lt;readonly number[]&gt;;</span>\n\n<span style=\"color: #008000\">// [string, boolean]</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> C = Writable&lt;readonly [string, boolean]&gt;;</span></code></div></pre>\n<h3 id=\"caveats\" style=\"position:relative;\"><a href=\"#caveats\" aria-label=\"caveats 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>Caveats</h3>\n<p>Despite its appearance, the <code>readonly</code> type modifier can only be used for syntax on array types and tuple types.\nIt is not a general-purpose type operator.</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> err1: readonly Set&lt;number&gt;; </span><span style=\"color: #008000\">// error!</span>\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> err2: readonly Array&lt;boolean&gt;; </span><span style=\"color: #008000\">// error!</span>\n\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> okay: readonly boolean[]; </span><span style=\"color: #008000\">// works fine</span></code></div></pre>\n<p>You can <a href=\"https://github.com/Microsoft/TypeScript/pull/29435\">see more details in the pull request</a>.</p>\n<h2 id=\"const-assertions\" style=\"position:relative;\"><a href=\"#const-assertions\" aria-label=\"const 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><code>const</code> assertions</h2>\n<p>TypeScript 3.4 introduces a new construct for literal values called <em><code>const</code></em> assertions.\nIts syntax is a type assertion with <code>const</code> in place of the type name (e.g. <code>123 as const</code>).\nWhen we construct new literal expressions with <code>const</code> assertions, we can signal to the language that</p>\n<ul>\n<li>no literal types in that expression should be widened (e.g. no going from <code>\"hello\"</code> to <code>string</code>)</li>\n<li>object literals get <code>readonly</code> properties</li>\n<li>array literals become <code>readonly</code> tuples</li>\n</ul>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #008000\">// Type '\"hello\"'</span>\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> x = </span><span style=\"color: #A31515\">\"hello\"</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">as</span><span style=\"color: #000000\"> const;</span>\n\n<span style=\"color: #008000\">// Type 'readonly [10, 20]'</span>\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> y = [</span><span style=\"color: #09835A\">10</span><span style=\"color: #000000\">, </span><span style=\"color: #09835A\">20</span><span style=\"color: #000000\">] </span><span style=\"color: #0000FF\">as</span><span style=\"color: #000000\"> const;</span>\n\n<span style=\"color: #008000\">// Type '{ readonly text: \"hello\" }'</span>\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> z = { text: </span><span style=\"color: #A31515\">\"hello\"</span><span style=\"color: #000000\"> } </span><span style=\"color: #0000FF\">as</span><span style=\"color: #000000\"> const;</span></code></div></pre>\n<p>Outside of <code>.tsx</code> files, the angle bracket assertion syntax can also be used.</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #008000\">// Type '\"hello\"'</span>\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> x = &lt;const&gt;</span><span style=\"color: #A31515\">\"hello\"</span><span style=\"color: #000000\">;</span>\n\n<span style=\"color: #008000\">// Type 'readonly [10, 20]'</span>\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> y = &lt;const&gt;[</span><span style=\"color: #09835A\">10</span><span style=\"color: #000000\">, </span><span style=\"color: #09835A\">20</span><span style=\"color: #000000\">];</span>\n\n<span style=\"color: #008000\">// Type '{ readonly text: \"hello\" }'</span>\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> z = &lt;const&gt;{ text: </span><span style=\"color: #A31515\">\"hello\"</span><span style=\"color: #000000\"> };</span></code></div></pre>\n<p>This feature means that types that would otherwise be used just to hint immutability to the compiler can often be omitted.</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #008000\">// Works with no types referenced or declared.</span>\n<span style=\"color: #008000\">// We only needed a single const assertion.</span>\n<span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> getShapes() {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> result = [</span>\n<span style=\"color: #000000\">        { kind: </span><span style=\"color: #A31515\">\"circle\"</span><span style=\"color: #000000\">, radius: </span><span style=\"color: #09835A\">100</span><span style=\"color: #000000\">, },</span>\n<span style=\"color: #000000\">        { kind: </span><span style=\"color: #A31515\">\"square\"</span><span style=\"color: #000000\">, sideLength: </span><span style=\"color: #09835A\">50</span><span style=\"color: #000000\">, },</span>\n<span style=\"color: #000000\">    ] </span><span style=\"color: #0000FF\">as</span><span style=\"color: #000000\"> const;</span>\n\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> result;</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">for</span><span style=\"color: #000000\"> (</span><span style=\"color: #0000FF\">const</span><span style=\"color: #000000\"> shape </span><span style=\"color: #0000FF\">of</span><span style=\"color: #000000\"> getShapes()) {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #008000\">// Narrows perfectly!</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">if</span><span style=\"color: #000000\"> (shape.kind === </span><span style=\"color: #A31515\">\"circle\"</span><span style=\"color: #000000\">) {</span>\n<span style=\"color: #000000\">        console.log(</span><span style=\"color: #A31515\">\"Circle radius\"</span><span style=\"color: #000000\">, shape.radius);</span>\n<span style=\"color: #000000\">    }</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">else</span><span style=\"color: #000000\"> {</span>\n<span style=\"color: #000000\">        console.log(</span><span style=\"color: #A31515\">\"Square side length\"</span><span style=\"color: #000000\">, shape.sideLength);</span>\n<span style=\"color: #000000\">    }</span>\n<span style=\"color: #000000\">}</span></code></div></pre>\n<p>Notice the above needed no type annotations.\nThe <code>const</code> assertion allowed TypeScript to take the most specific type of the expression.</p>\n<p>This can even be used to enable <code>enum</code>-like patterns in plain JavaScript code if you choose not to use TypeScript’s <code>enum</code> construct.</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">export</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">const</span><span style=\"color: #000000\"> Colors = {</span>\n<span style=\"color: #000000\">    red: </span><span style=\"color: #A31515\">\"RED\"</span><span style=\"color: #000000\">,</span>\n<span style=\"color: #000000\">    blue: </span><span style=\"color: #A31515\">\"BLUE\"</span><span style=\"color: #000000\">,</span>\n<span style=\"color: #000000\">    green: </span><span style=\"color: #A31515\">\"GREEN\"</span><span style=\"color: #000000\">,</span>\n<span style=\"color: #000000\">} </span><span style=\"color: #0000FF\">as</span><span style=\"color: #000000\"> const;</span>\n\n<span style=\"color: #008000\">// or use an 'export default'</span>\n\n<span style=\"color: #0000FF\">export</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">default</span><span style=\"color: #000000\"> {</span>\n<span style=\"color: #000000\">    red: </span><span style=\"color: #A31515\">\"RED\"</span><span style=\"color: #000000\">,</span>\n<span style=\"color: #000000\">    blue: </span><span style=\"color: #A31515\">\"BLUE\"</span><span style=\"color: #000000\">,</span>\n<span style=\"color: #000000\">    green: </span><span style=\"color: #A31515\">\"GREEN\"</span><span style=\"color: #000000\">,</span>\n<span style=\"color: #000000\">} </span><span style=\"color: #0000FF\">as</span><span style=\"color: #000000\"> const;</span></code></div></pre>\n<h3 id=\"caveats-1\" style=\"position:relative;\"><a href=\"#caveats-1\" aria-label=\"caveats 1 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>Caveats</h3>\n<p>One thing to note is that <code>const</code> assertions can only be applied immediately on simple literal expressions.</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #008000\">// Error! A 'const' assertion can only be applied to a</span>\n<span style=\"color: #008000\">// to a string, number, boolean, array, or object literal.</span>\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> a = (Math.random() &lt; </span><span style=\"color: #09835A\">0.5</span><span style=\"color: #000000\"> ? </span><span style=\"color: #09835A\">0</span><span style=\"color: #000000\"> : </span><span style=\"color: #09835A\">1</span><span style=\"color: #000000\">) </span><span style=\"color: #0000FF\">as</span><span style=\"color: #000000\"> const;</span>\n\n<span style=\"color: #008000\">// Works!</span>\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> b = Math.random() &lt; </span><span style=\"color: #09835A\">0.5</span><span style=\"color: #000000\"> ?</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #09835A\">0</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">as</span><span style=\"color: #000000\"> const :</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #09835A\">1</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">as</span><span style=\"color: #000000\"> const;</span></code></div></pre>\n<p>Another thing to keep in mind is that <code>const</code> contexts don’t immediately convert an expression to be fully immutable.</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> arr = [</span><span style=\"color: #09835A\">1</span><span style=\"color: #000000\">, </span><span style=\"color: #09835A\">2</span><span style=\"color: #000000\">, </span><span style=\"color: #09835A\">3</span><span style=\"color: #000000\">, </span><span style=\"color: #09835A\">4</span><span style=\"color: #000000\">];</span>\n\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> foo = {</span>\n<span style=\"color: #000000\">    name: </span><span style=\"color: #A31515\">\"foo\"</span><span style=\"color: #000000\">,</span>\n<span style=\"color: #000000\">    contents: arr,</span>\n<span style=\"color: #000000\">} </span><span style=\"color: #0000FF\">as</span><span style=\"color: #000000\"> const;</span>\n\n<span style=\"color: #000000\">foo.name = </span><span style=\"color: #A31515\">\"bar\"</span><span style=\"color: #000000\">;   </span><span style=\"color: #008000\">// error!</span>\n<span style=\"color: #000000\">foo.contents = [];  </span><span style=\"color: #008000\">// error!</span>\n\n<span style=\"color: #000000\">foo.contents.push(</span><span style=\"color: #09835A\">5</span><span style=\"color: #000000\">); </span><span style=\"color: #008000\">// ...works!</span></code></div></pre>\n<p>For more details, you can <a href=\"https://github.com/Microsoft/TypeScript/pull/29510\">check out the respective pull request</a>.</p>\n<h2 id=\"type-checking-for-globalthis\" style=\"position:relative;\"><a href=\"#type-checking-for-globalthis\" aria-label=\"type checking for globalthis 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-checking for <code>globalThis</code></h2>\n<p>TypeScript 3.4 introduces support for type-checking ECMAScript’s new <code>globalThis</code> - a global variable that, well, refers to the global scope.\nUnlike the above solutions, <code>globalThis</code> provides a standard way for accessing the global scope which can be used across different environments.</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #008000\">// in a global file:</span>\n\n<span style=\"color: #0000FF\">var</span><span style=\"color: #000000\"> abc = </span><span style=\"color: #09835A\">100</span><span style=\"color: #000000\">;</span>\n\n<span style=\"color: #008000\">// Refers to 'abc' from above.</span>\n<span style=\"color: #000000\">globalThis.abc = </span><span style=\"color: #09835A\">200</span><span style=\"color: #000000\">;</span></code></div></pre>\n<p>Note that global variables declared with <code>let</code> and <code>const</code> don’t show up on <code>globalThis</code>.</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> answer = </span><span style=\"color: #09835A\">42</span><span style=\"color: #000000\">;</span>\n\n<span style=\"color: #008000\">// error! Property 'answer' does not exist on 'typeof globalThis'.</span>\n<span style=\"color: #000000\">globalThis.answer = </span><span style=\"color: #09835A\">333333</span><span style=\"color: #000000\">;</span></code></div></pre>\n<p>It’s also important to note that TypeScript doesn’t transform references to <code>globalThis</code> when compiling to older versions of ECMAScript.\nAs such, unless you’re targeting evergreen browsers (which already support <code>globalThis</code>), you may want to <a href=\"https://github.com/ljharb/globalThis\">use an appropriate polyfill</a> instead.</p>\n<p>For more details on the implementation, see <a href=\"https://github.com/Microsoft/TypeScript/pull/29332\">the feature’s pull request</a>.</p>","headings":[{"value":"Faster subsequent builds with the --incremental flag","depth":2},{"value":"Composite projects","depth":3},{"value":"outFile","depth":3},{"value":"Higher order type inference from generic functions","depth":2},{"value":"Improvements for ReadonlyArray and readonly tuples","depth":2},{"value":"A new syntax for ReadonlyArray","depth":3},{"value":"readonly tuples","depth":3},{"value":"readonly mapped type modifiers and readonly arrays","depth":3},{"value":"Caveats","depth":3},{"value":"const assertions","depth":2},{"value":"Caveats","depth":3},{"value":"Type-checking for globalThis","depth":2}],"frontmatter":{"permalink":"/docs/handbook/release-notes/typescript-3-4.html","title":"TypeScript 3.4"}}},"pageContext":{"slug":"/docs/handbook/release-notes/typescript-3-4.html","isOldHandbook":true}}}