{"componentChunkName":"component---src-templates-handbook-tsx","path":"/docs/handbook/release-notes/typescript-3-1.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":"826a21c5-2817-5959-8407-9760d2d36b64","excerpt":"Mapped types on tuples and arrays In TypeScript 3.1, mapped object types[1] over tuples and arrays now produce new tuples/arrays, rather than creating a new…","html":"<h2 id=\"mapped-types-on-tuples-and-arrays\" style=\"position:relative;\"><a href=\"#mapped-types-on-tuples-and-arrays\" aria-label=\"mapped types on tuples and 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>Mapped types on tuples and arrays</h2>\n<p>In TypeScript 3.1, mapped object types<sup><a href=\"#ts-3-1-only-homomorphic\">[1]</a></sup> over tuples and arrays now produce new tuples/arrays, rather than creating a new type where members like <code>push()</code>, <code>pop()</code>, and <code>length</code> are converted.\nFor example:</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\"> MapToPromise&lt;T&gt; = { [K </span><span style=\"color: #0000FF\">in</span><span style=\"color: #000000\"> keyof T]: Promise&lt;T[K]&gt; };</span>\n\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> Coordinate = [number, number]</span>\n\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> PromiseCoordinate = MapToPromise&lt;Coordinate&gt;; </span><span style=\"color: #008000\">// [Promise&lt;number&gt;, Promise&lt;number&gt;]</span></code></div></pre>\n<p><code>MapToPromise</code> takes a type <code>T</code>, and when that type is a tuple like <code>Coordinate</code>, only the numeric properties are converted.\nIn <code>[number, number]</code>, there are two numerically named properties: <code>0</code> and <code>1</code>.\nWhen given a tuple like that, <code>MapToPromise</code> will create a new tuple where the <code>0</code> and <code>1</code> properties are <code>Promise</code>s of the original type.\nSo the resulting type <code>PromiseCoordinate</code> ends up with the type <code>[Promise&#x3C;number>, Promise&#x3C;number>]</code>.</p>\n<h2 id=\"properties-declarations-on-functions\" style=\"position:relative;\"><a href=\"#properties-declarations-on-functions\" aria-label=\"properties declarations on 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>Properties declarations on functions</h2>\n<p>TypeScript 3.1 brings the ability to define properties on function declarations and <code>const</code>-declared functions, simply by assigning to properties on these functions in the same scope.\nThis allows us to write canonical JavaScript code without resorting to <code>namespace</code> hacks.\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\"> readImage(path: string, callback: (err: any, image: Image) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> void) {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #008000\">// ...</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #000000\">readImage.sync = (path: string) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">const</span><span style=\"color: #000000\"> contents = fs.readFileSync(path);</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> decodeImageSync(contents);</span>\n<span style=\"color: #000000\">}</span></code></div></pre>\n<p>Here, we have a function <code>readImage</code> which reads an image in a non-blocking asynchronous way.\nIn addition to <code>readImage</code>, we’ve provided a convenience function on <code>readImage</code> itself called <code>readImage.sync</code>.</p>\n<p>While ECMAScript exports are often a better way of providing this functionality, this new support allows code written in this style to “just work” TypeScript.\nAdditionally, this approach for property declarations allows us to express common patterns like <code>defaultProps</code> and <code>propTypes</code> on React function components (formerly known as SFCs).</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\"> FooComponent = ({ name }) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> (</span>\n<span style=\"color: #000000\">    &lt;div&gt;Hello! I am {name}&lt;/div&gt;</span>\n<span style=\"color: #000000\">);</span>\n\n<span style=\"color: #000000\">FooComponent.defaultProps = {</span>\n<span style=\"color: #000000\">    name: </span><span style=\"color: #A31515\">\"(anonymous)\"</span><span style=\"color: #000000\">,</span>\n<span style=\"color: #000000\">};</span></code></div></pre>\n<!--\nfs.readFile(path, (err, data) => {\n        if (err) callback(err, undefined);\n        else decodeImage(data, (err, image) => {\n            if (err) callback(err, undefined);\n            else callback(undefined, image);\n        });\n    });\n-->\n<hr>\n<p><sup id=\"ts-3-1-only-homomorphic\">[1]</sup> More specifically, homomorphic mapped types like in the above form.</p>\n<h2 id=\"version-selection-with-typesversions\" style=\"position:relative;\"><a href=\"#version-selection-with-typesversions\" aria-label=\"version selection with typesversions 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>Version selection with <code>typesVersions</code></h2>\n<p>Feedback from our community, as well as our own experience, has shown us that leveraging the newest TypeScript features while also accommodating users on the older versions are difficult.\nTypeScript introduces a new feature called <code>typesVersions</code> to help accommodate these scenarios.</p>\n<p>When using Node module resolution in TypeScript 3.1, when TypeScript cracks open a <code>package.json</code> file to figure out which files it needs to read, it first looks at a new field called <code>typesVersions</code>.\nA <code>package.json</code> with a <code>typesVersions</code> field might look like this:</p>\n<pre class=\"shiki\"><div class=\"language-id\">json</div><div class='code-container'><code><span style=\"color: #000000\">{</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0451A5\">\"name\"</span><span style=\"color: #000000\">: </span><span style=\"color: #A31515\">\"package-name\"</span><span style=\"color: #000000\">,</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0451A5\">\"version\"</span><span style=\"color: #000000\">: </span><span style=\"color: #A31515\">\"1.0\"</span><span style=\"color: #000000\">,</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0451A5\">\"types\"</span><span style=\"color: #000000\">: </span><span style=\"color: #A31515\">\"./index.d.ts\"</span><span style=\"color: #000000\">,</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0451A5\">\"typesVersions\"</span><span style=\"color: #000000\">: {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0451A5\">\"&gt;=3.1\"</span><span style=\"color: #000000\">: { </span><span style=\"color: #0451A5\">\"*\"</span><span style=\"color: #000000\">: [</span><span style=\"color: #A31515\">\"ts3.1/*\"</span><span style=\"color: #000000\">] }</span>\n<span style=\"color: #000000\">  }</span>\n<span style=\"color: #000000\">}</span></code></div></pre>\n<p>This <code>package.json</code> tells TypeScript to check whether the current version of TypeScript is running.\nIf it’s 3.1 or later, it figures out the path you’ve imported relative to the package, and reads from the package’s <code>ts3.1</code> folder.\nThat’s what that <code>{ \"*\": [\"ts3.1/*\"] }</code> means - if you’re familiar with path mapping today, it works exactly like that.</p>\n<p>So in the above example, if we’re importing from <code>\"package-name\"</code>, we’ll try to resolve from <code>[...]/node_modules/package-name/ts3.1/index.d.ts</code> (and other relevant paths) when running in TypeScript 3.1.\nIf we import from <code>package-name/foo</code>, we’ll try to look for <code>[...]/node_modules/package-name/ts3.1/foo.d.ts</code> and <code>[...]/node_modules/package-name/ts3.1/foo/index.d.ts</code>.</p>\n<p>What if we’re not running in TypeScript 3.1 in this example?\nWell, if none of the fields in <code>typesVersions</code> get matched, TypeScript falls back to the <code>types</code> field, so here TypeScript 3.0 and earlier will be redirected to <code>[...]/node_modules/package-name/index.d.ts</code>.</p>\n<h2 id=\"matching-behavior\" style=\"position:relative;\"><a href=\"#matching-behavior\" aria-label=\"matching behavior 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>Matching behavior</h2>\n<p>The way that TypeScript decides on whether a version of the compiler &#x26; language matches is by using Node’s <a href=\"https://github.com/npm/node-semver#ranges\">semver ranges</a>.</p>\n<h2 id=\"multiple-fields\" style=\"position:relative;\"><a href=\"#multiple-fields\" aria-label=\"multiple fields 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>Multiple fields</h2>\n<p><code>typesVersions</code> can support multiple fields where each field name is specified by the range to match on.</p>\n<pre class=\"shiki\"><div class=\"language-id\">json</div><div class='code-container'><code><span style=\"color: #000000\">{</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0451A5\">\"name\"</span><span style=\"color: #000000\">: </span><span style=\"color: #A31515\">\"package-name\"</span><span style=\"color: #000000\">,</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0451A5\">\"version\"</span><span style=\"color: #000000\">: </span><span style=\"color: #A31515\">\"1.0\"</span><span style=\"color: #000000\">,</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0451A5\">\"types\"</span><span style=\"color: #000000\">: </span><span style=\"color: #A31515\">\"./index.d.ts\"</span><span style=\"color: #000000\">,</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0451A5\">\"typesVersions\"</span><span style=\"color: #000000\">: {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0451A5\">\"&gt;=3.2\"</span><span style=\"color: #000000\">: { </span><span style=\"color: #0451A5\">\"*\"</span><span style=\"color: #000000\">: [</span><span style=\"color: #A31515\">\"ts3.2/*\"</span><span style=\"color: #000000\">] },</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0451A5\">\"&gt;=3.1\"</span><span style=\"color: #000000\">: { </span><span style=\"color: #0451A5\">\"*\"</span><span style=\"color: #000000\">: [</span><span style=\"color: #A31515\">\"ts3.1/*\"</span><span style=\"color: #000000\">] }</span>\n<span style=\"color: #000000\">  }</span>\n<span style=\"color: #000000\">}</span></code></div></pre>\n<p>Since ranges have the potential to overlap, determining which redirect applies is order-specific.\nThat means in the above example, even though both the <code>>=3.2</code> and the <code>>=3.1</code> matchers support TypeScript 3.2 and above, reversing the order could have different behavior, so the above sample would not be equivalent to the following.</p>\n<pre class=\"shiki\"><div class=\"language-id\">json</div><div class='code-container'><code><span style=\"color: #000000\">{</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0451A5\">\"name\"</span><span style=\"color: #000000\">: </span><span style=\"color: #A31515\">\"package-name\"</span><span style=\"color: #000000\">,</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0451A5\">\"version\"</span><span style=\"color: #000000\">: </span><span style=\"color: #A31515\">\"1.0\"</span><span style=\"color: #000000\">,</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0451A5\">\"types\"</span><span style=\"color: #000000\">: </span><span style=\"color: #A31515\">\"./index.d.ts\"</span><span style=\"color: #000000\">,</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0451A5\">\"typesVersions\"</span><span style=\"color: #000000\">: {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #008000\">// NOTE: this doesn't work!</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0451A5\">\"&gt;=3.1\"</span><span style=\"color: #000000\">: { </span><span style=\"color: #0451A5\">\"*\"</span><span style=\"color: #000000\">: [</span><span style=\"color: #A31515\">\"ts3.1/*\"</span><span style=\"color: #000000\">] },</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0451A5\">\"&gt;=3.2\"</span><span style=\"color: #000000\">: { </span><span style=\"color: #0451A5\">\"*\"</span><span style=\"color: #000000\">: [</span><span style=\"color: #A31515\">\"ts3.2/*\"</span><span style=\"color: #000000\">] }</span>\n<span style=\"color: #000000\">  }</span>\n<span style=\"color: #000000\">}</span></code></div></pre>","headings":[{"value":"Mapped types on tuples and arrays","depth":2},{"value":"Properties declarations on functions","depth":2},{"value":"Version selection with typesVersions","depth":2},{"value":"Matching behavior","depth":2},{"value":"Multiple fields","depth":2}],"frontmatter":{"permalink":"/docs/handbook/release-notes/typescript-3-1.html","title":"TypeScript 3.1"}}},"pageContext":{"slug":"/docs/handbook/release-notes/typescript-3-1.html","isOldHandbook":true}}}