{"componentChunkName":"component---src-templates-handbook-tsx","path":"/docs/handbook/release-notes/typescript-2-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":"270b68c6-2f88-5ea5-b43e-3d2b1ec97c0b","excerpt":"Dynamic Import Expressions Dynamic import expressions are a new feature and part of ECMAScript that allows users to asynchronously request a module at any…","html":"<h2 id=\"dynamic-import-expressions\" style=\"position:relative;\"><a href=\"#dynamic-import-expressions\" aria-label=\"dynamic import 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>Dynamic Import Expressions</h2>\n<p>Dynamic <code>import</code> expressions are a new feature and part of ECMAScript that allows users to asynchronously request a module at any arbitrary point in your program.</p>\n<p>This means that you can conditionally and lazily import other modules and libraries.\nFor example, here’s an <code>async</code> function that only imports a utility library when it’s needed:</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">async</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> getZipFile(name: string, files: File[]): Promise&lt;File&gt; {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">const</span><span style=\"color: #000000\"> zipUtil = </span><span style=\"color: #0000FF\">await</span><span style=\"color: #000000\"> import(</span><span style=\"color: #A31515\">'./utils/create-zip-file'</span><span style=\"color: #000000\">);</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">const</span><span style=\"color: #000000\"> zipContents = </span><span style=\"color: #0000FF\">await</span><span style=\"color: #000000\"> zipUtil.getContentAsBlob(files);</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">new</span><span style=\"color: #000000\"> File(zipContents, name);</span>\n<span style=\"color: #000000\">}</span></code></div></pre>\n<p>Many bundlers have support for automatically splitting output bundles based on these <code>import</code> expressions, so consider using this new feature with the <code>esnext</code> module target.</p>\n<h2 id=\"string-enums\" style=\"position:relative;\"><a href=\"#string-enums\" aria-label=\"string enums 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>String Enums</h2>\n<p>TypeScript 2.4 now allows enum members to contain string initializers.</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">enum</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\">    Green = </span><span style=\"color: #A31515\">\"GREEN\"</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\">}</span></code></div></pre>\n<p>The caveat is that string-initialized enums can’t be reverse-mapped to get the original enum member name.\nIn other words, you can’t write <code>Colors[\"RED\"]</code> to get the string <code>\"Red\"</code>.</p>\n<h2 id=\"improved-inference-for-generics\" style=\"position:relative;\"><a href=\"#improved-inference-for-generics\" aria-label=\"improved inference for generics 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>Improved inference for generics</h2>\n<p>TypeScript 2.4 introduces a few wonderful changes around the way generics are inferred.</p>\n<h3 id=\"return-types-as-inference-targets\" style=\"position:relative;\"><a href=\"#return-types-as-inference-targets\" aria-label=\"return types as inference targets 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>Return types as inference targets</h3>\n<p>For one, TypeScript can now make inferences for the return type of a call.\nThis can improve your experience and catch errors.\nSomething that now works:</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\"> arrayMap&lt;T, U&gt;(f: (x: T) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> U): (a: T[]) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> U[] {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> a </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> a.map(f);</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">const</span><span style=\"color: #000000\"> lengths: (a: string[]) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> number[] = arrayMap(s </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> s.length);</span></code></div></pre>\n<p>As an example of new errors you might spot as a result:</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\"> x: Promise&lt;string&gt; = </span><span style=\"color: #0000FF\">new</span><span style=\"color: #000000\"> Promise(resolve </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> {</span>\n<span style=\"color: #000000\">    resolve(</span><span style=\"color: #09835A\">10</span><span style=\"color: #000000\">);</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #008000\">//      ~~ Error!</span>\n<span style=\"color: #000000\">});</span></code></div></pre>\n<h3 id=\"type-parameter-inference-from-contextual-types\" style=\"position:relative;\"><a href=\"#type-parameter-inference-from-contextual-types\" aria-label=\"type parameter inference from contextual types 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 parameter inference from contextual types</h3>\n<p>Prior to TypeScript 2.4, in the following example</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\"> f: &lt;T&gt;(x: T) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> T = y </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> y;</span></code></div></pre>\n<p><code>y</code> would have the type <code>any</code>.\nThis meant the program would type-check, but you could technically do anything with <code>y</code>, such as the following:</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\"> f: &lt;T&gt;(x: T) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> T = y </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> y() + y.foo.bar;</span></code></div></pre>\n<p>That last example isn’t actually type-safe.</p>\n<p>In TypeScript 2.4, the function on the right side implicitly <em>gains</em> type parameters, and <code>y</code> is inferred to have the type of that type-parameter.</p>\n<p>If you use <code>y</code> in a way that the type parameter’s constraint doesn’t support, you’ll correctly get an error.\nIn this case, the constraint of <code>T</code> was (implicitly) <code>{}</code>, so the last example will appropriately fail.</p>\n<h3 id=\"stricter-checking-for-generic-functions\" style=\"position:relative;\"><a href=\"#stricter-checking-for-generic-functions\" aria-label=\"stricter checking for 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>Stricter checking for generic functions</h3>\n<p>TypeScript now tries to unify type parameters when comparing two single-signature types.\nAs a result, you’ll get stricter checks when relating two generic signatures, and may catch some bugs.</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\"> A = &lt;T, U&gt;(x: T, y: U) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> [T, U];</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> B = &lt;S&gt;(x: S, y: S) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> [S, S];</span>\n\n<span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> f(a: A, b: B) {</span>\n<span style=\"color: #000000\">    a = b;  </span><span style=\"color: #008000\">// Error</span>\n<span style=\"color: #000000\">    b = a;  </span><span style=\"color: #008000\">// Ok</span>\n<span style=\"color: #000000\">}</span></code></div></pre>\n<h2 id=\"strict-contravariance-for-callback-parameters\" style=\"position:relative;\"><a href=\"#strict-contravariance-for-callback-parameters\" aria-label=\"strict contravariance for callback parameters 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>Strict contravariance for callback parameters</h2>\n<p>TypeScript has always compared parameters in a bivariant way.\nThere are a number of reasons for this, but by-and-large this was not been a huge issue for our users until we saw some of the adverse effects it had with <code>Promise</code>s and <code>Observable</code>s.</p>\n<p>TypeScript 2.4 introduces tightens this up when relating two callback types. For example:</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\"> Mappable&lt;T&gt; {</span>\n<span style=\"color: #000000\">    map&lt;U&gt;(f: (x: T) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> U): Mappable&lt;U&gt;;</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\"> a: Mappable&lt;number&gt;;</span>\n<span style=\"color: #0000FF\">declare</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> b: Mappable&lt;string | number&gt;;</span>\n\n<span style=\"color: #000000\">a = b;</span>\n<span style=\"color: #000000\">b = a;</span></code></div></pre>\n<p>Prior to TypeScript 2.4, this example would succeed.\nWhen relating the types of <code>map</code>, TypeScript would bidirectionally relate their parameters (i.e. the type of <code>f</code>).\nWhen relating each <code>f</code>, TypeScript would also bidirectionally relate the type of <em>those</em> parameters.</p>\n<p>When relating the type of <code>map</code> in TS 2.4, the language will check whether each parameter is a callback type, and if so, it will ensure that those parameters are checked in a contravariant manner with respect to the current relation.</p>\n<p>In other words, TypeScript now catches the above bug, which may be a breaking change for some users, but will largely be helpful.</p>\n<h2 id=\"weak-type-detection\" style=\"position:relative;\"><a href=\"#weak-type-detection\" aria-label=\"weak type detection 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>Weak Type Detection</h2>\n<p>TypeScript 2.4 introduces the concept of “weak types”.\nAny type that contains nothing but a set of all-optional properties is considered to be <em>weak</em>.\nFor example, this <code>Options</code> type is a weak type:</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\"> Options {</span>\n<span style=\"color: #000000\">    data?: string,</span>\n<span style=\"color: #000000\">    timeout?: number,</span>\n<span style=\"color: #000000\">    maxRetries?: number,</span>\n<span style=\"color: #000000\">}</span></code></div></pre>\n<p>In TypeScript 2.4, it’s now an error to assign anything to a weak type when there’s no overlap in properties.\nFor example:</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\"> sendMessage(options: Options) {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #008000\">// ...</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">const</span><span style=\"color: #000000\"> opts = {</span>\n<span style=\"color: #000000\">    payload: </span><span style=\"color: #A31515\">\"hello world!\"</span><span style=\"color: #000000\">,</span>\n<span style=\"color: #000000\">    retryOnFail: </span><span style=\"color: #0000FF\">true</span><span style=\"color: #000000\">,</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #008000\">// Error!</span>\n<span style=\"color: #000000\">sendMessage(opts);</span>\n<span style=\"color: #008000\">// No overlap between the type of 'opts' and 'Options' itself.</span>\n<span style=\"color: #008000\">// Maybe we meant to use 'data'/'maxRetries' instead of 'payload'/'retryOnFail'.</span></code></div></pre>\n<p>You can think of this as TypeScript “toughening up” the weak guarantees of these types to catch what would otherwise be silent bugs.</p>\n<p>Since this is a breaking change, you may need to know about the workarounds which are the same as those for strict object literal checks:</p>\n<ol>\n<li>Declare the properties if they really do exist.</li>\n<li>Add an index signature to the weak type (i.e. <code>[propName: string]: {}</code>).</li>\n<li>Use a type assertion (i.e. <code>opts as Options</code>).</li>\n</ol>","headings":[{"value":"Dynamic Import Expressions","depth":2},{"value":"String Enums","depth":2},{"value":"Improved inference for generics","depth":2},{"value":"Return types as inference targets","depth":3},{"value":"Type parameter inference from contextual types","depth":3},{"value":"Stricter checking for generic functions","depth":3},{"value":"Strict contravariance for callback parameters","depth":2},{"value":"Weak Type Detection","depth":2}],"frontmatter":{"permalink":"/docs/handbook/release-notes/typescript-2-4.html","title":"TypeScript 2.4"}}},"pageContext":{"slug":"/docs/handbook/release-notes/typescript-2-4.html","isOldHandbook":true}}}