{"componentChunkName":"component---src-templates-handbook-tsx","path":"/docs/handbook/release-notes/typescript-2-4.html","result":{"data":{"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\"><a href=\"#dynamic-import-expressions\" aria-label=\"dynamic import expressions permalink\" class=\"anchor\"><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\"><a href=\"#string-enums\" aria-label=\"string enums permalink\" class=\"anchor\"><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\"><a href=\"#improved-inference-for-generics\" aria-label=\"improved inference for generics permalink\" class=\"anchor\"><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\"><a href=\"#return-types-as-inference-targets\" aria-label=\"return types as inference targets permalink\" class=\"anchor\"><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\"><a href=\"#type-parameter-inference-from-contextual-types\" aria-label=\"type parameter inference from contextual types permalink\" class=\"anchor\"><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\"><a href=\"#stricter-checking-for-generic-functions\" aria-label=\"stricter checking for generic functions permalink\" class=\"anchor\"><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\"><a href=\"#strict-contravariance-for-callback-parameters\" aria-label=\"strict contravariance for callback parameters permalink\" class=\"anchor\"><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\"><a href=\"#weak-type-detection\" aria-label=\"weak type detection permalink\" class=\"anchor\"><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}}}