{"id":2846,"date":"2021-01-12T16:48:28","date_gmt":"2021-01-13T00:48:28","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/typescript\/?p=2846"},"modified":"2021-01-12T16:48:28","modified_gmt":"2021-01-13T00:48:28","slug":"announcing-typescript-4-2-beta","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-4-2-beta\/","title":{"rendered":"Announcing TypeScript 4.2 Beta"},"content":{"rendered":"<p>Today we&#8217;re excited to announce the availability of TypeScript 4.2 Beta!<\/p>\n<p>To get started using the beta, you can get it <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.TypeScript.MSBuild\" rel=\"nofollow\">through NuGet<\/a>, or use npm with the following command:<\/p>\n<div class=\"highlight highlight-source-shell\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\">npm install typescript@beta<\/pre>\n<\/div>\n<p>You can also get editor support by<\/p>\n<ul>\n<li><a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=TypeScriptTeam.TypeScript-42beta\" rel=\"nofollow\">Downloading for Visual Studio 2019\/2017<\/a><\/li>\n<li>Following directions for <a href=\"https:\/\/code.visualstudio.com\/Docs\/languages\/typescript#_using-newer-typescript-versions\" rel=\"nofollow\">Visual Studio Code<\/a> and <a href=\"https:\/\/github.com\/Microsoft\/TypeScript-Sublime-Plugin\/#note-using-different-versions-of-typescript\">Sublime Text<\/a>.<\/li>\n<\/ul>\n<p>Let&#8217;s take a look at what&#8217;s in store for TypeScript 4.2!<\/p>\n<h2>Leading\/Middle Rest Elements in Tuple Types<\/h2>\n<p>In TypeScript, tuple types are meant to model arrays with specific lengths and element types.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #148A14;\">\/\/ A tuple that stores a pair of numbers<\/span>\r\n<span class=\"pl-k\">let<\/span> <span class=\"pl-s1\">a<\/span>: <span class=\"pl-kos\">[<\/span><span style=\"color: #0000ff;\">number<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #0000ff;\">number<\/span><span class=\"pl-kos\">]<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span><span style=\"color: #09885A;\">1<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #09885A;\">2<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #148A14;\">\/\/ A tuple that stores a string, a number, and a boolean<\/span>\r\n<span class=\"pl-k\">let<\/span> <span class=\"pl-s1\">b<\/span>: <span class=\"pl-kos\">[<\/span><span style=\"color: #0000ff;\">string<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #0000ff;\">number<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #0000ff;\">boolean<\/span><span class=\"pl-kos\">]<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span><span style=\"color: #a31515;\">\"hello\"<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #09885A;\">42<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #0000ff;\">true<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>Over time, TypeScript&#8217;s tuple types have become more and more sophisticated, since they&#8217;re also used to model things like parameter lists in JavaScript. As a result, they can have optional elements and rest elements, and can even have labels for tooling and readability.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #148A14;\">\/\/ A tuple that has either one or two strings.<\/span>\r\n<span class=\"pl-k\">let<\/span> <span class=\"pl-s1\">c<\/span>: <span class=\"pl-kos\">[<\/span><span style=\"color: #0000ff;\">string<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #0000ff;\">string<\/span>?<span class=\"pl-kos\">]<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span><span style=\"color: #a31515;\">\"hello\"<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-s1\">c<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span><span style=\"color: #a31515;\">\"hello\"<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #a31515;\">\"world\"<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #148A14;\">\/\/ A labeled tuple that has either one or two strings.<\/span>\r\n<span class=\"pl-k\">let<\/span> <span class=\"pl-s1\">d<\/span>: <span class=\"pl-kos\">[<\/span><span class=\"pl-smi\">first<\/span>: string<span class=\"pl-kos\">,<\/span> <span class=\"pl-smi\">second<\/span>?: string<span class=\"pl-kos\">]<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span><span style=\"color: #a31515;\">\"hello\"<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-s1\">d<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span><span style=\"color: #a31515;\">\"hello\"<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #a31515;\">\"world\"<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #148A14;\">\/\/ A tuple with a *rest element* - holds at least 2 strings at the front,<\/span>\r\n<span style=\"color: #148A14;\">\/\/ and any number of booleans at the back.<\/span>\r\n<span class=\"pl-k\">let<\/span> <span class=\"pl-s1\">e<\/span>: <span class=\"pl-kos\">[<\/span><span style=\"color: #0000ff;\">string<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #0000ff;\">string<\/span><span class=\"pl-kos\">,<\/span> ...<span style=\"color: #0000ff;\">boolean<\/span><span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span class=\"pl-s1\">e<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span><span style=\"color: #a31515;\">\"hello\"<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #a31515;\">\"world\"<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-s1\">e<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span><span style=\"color: #a31515;\">\"hello\"<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #a31515;\">\"world\"<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #0000ff;\">false<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-s1\">e<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span><span style=\"color: #a31515;\">\"hello\"<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #a31515;\">\"world\"<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #0000ff;\">true<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #0000ff;\">false<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #0000ff;\">true<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>In TypeScript 4.2, rest elements specifically been expanded in how they can be used. In prior versions, TypeScript only allowed <code>...rest<\/code> elements at the very last position of a tuple type.<\/p>\n<p>However, now rest elements can occur <em>anywhere<\/em> within a tuple &#8211; with only a few restrictions.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span class=\"pl-k\">let<\/span> <span class=\"pl-s1\">foo<\/span>: <span class=\"pl-kos\">[<\/span>...<span style=\"color: #0000ff;\">string<\/span><span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #0000ff;\">number<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span class=\"pl-s1\">foo<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span><span style=\"color: #09885A;\">123<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-s1\">foo<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span><span style=\"color: #a31515;\">\"hello\"<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #09885A;\">123<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-s1\">foo<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span><span style=\"color: #a31515;\">\"hello!\"<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #a31515;\">\"hello!\"<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #a31515;\">\"hello!\"<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #09885A;\">123<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span class=\"pl-k\">let<\/span> <span class=\"pl-s1\">bar<\/span>: <span class=\"pl-kos\">[<\/span><span style=\"color: #0000ff;\">boolean<\/span><span class=\"pl-kos\">,<\/span> ...<span style=\"color: #0000ff;\">string<\/span><span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #0000ff;\">boolean<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span class=\"pl-s1\">bar<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span><span style=\"color: #0000ff;\">true<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #0000ff;\">false<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-s1\">bar<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span><span style=\"color: #0000ff;\">true<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #a31515;\">\"some text\"<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #0000ff;\">false<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-s1\">bar<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span><span style=\"color: #0000ff;\">true<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #a31515;\">\"some\"<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #a31515;\">\"separated\"<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #a31515;\">\"text\"<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #0000ff;\">false<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>The only restriction is that a rest element can be placed anywhere in a tuple, so long as it&#8217;s not followed by another optional element or rest element. In other words, only one rest element per tuple, and no optional elements after rest elements.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span class=\"pl-k\">interface<\/span> <span style=\"color: #267F99;\">Clown<\/span> <span class=\"pl-kos\">{<\/span> <span style=\"color: #148A14;\">\/*...*\/<\/span> <span class=\"pl-kos\">}<\/span>\r\n<span class=\"pl-k\">interface<\/span> <span style=\"color: #267F99;\">Joker<\/span> <span class=\"pl-kos\">{<\/span> <span style=\"color: #148A14;\">\/*...*\/<\/span> <span class=\"pl-kos\">}<\/span>\r\n\r\n<span class=\"pl-k\">let<\/span> <span style=\"color: #267F99;\">StealersWheel<\/span>: <span class=\"pl-kos\">[<\/span>...<span style=\"color: #267F99;\">Clown<\/span><span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #a31515;\">\"me\"<\/span><span class=\"pl-kos\">,<\/span> ...<span style=\"color: #267F99;\">Joker<\/span><span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #148A14;\">\/\/                                    ~~~~~~~~~~ Error!<\/span>\r\n<span style=\"color: #148A14;\">\/\/ A rest element cannot follow another rest element.<\/span>\r\n\r\n<span class=\"pl-k\">let<\/span> <span style=\"color: #0000ff;\">StringssAndMaybeBoolean<\/span>: <span class=\"pl-kos\">[<\/span>...<span style=\"color: #0000ff;\">string<\/span><span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #0000ff;\">boolean<\/span>?<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #148A14;\">\/\/                                         ~~~~~~~~ Error!<\/span>\r\n<span style=\"color: #148A14;\">\/\/ An optional element cannot follow a rest element.<\/span><\/pre>\n<\/div>\n<p>These non-trailing rest elements can be used to model functions that take any number of leading arguments, followed by a few fixed ones.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span class=\"pl-k\">declare<\/span> <span class=\"pl-k\">function<\/span> <span class=\"pl-s1\">doStuff<\/span><span class=\"pl-kos\">(<\/span>...<span class=\"pl-s1\">args<\/span>: <span class=\"pl-kos\">[<\/span>...<span class=\"pl-s1\">names<\/span>: <span style=\"color: #0000ff;\">string<\/span><span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">shouldCapitalize<\/span>: <span style=\"color: #0000ff;\">boolean<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-smi\"><span class=\"pl-k\">void<\/span><\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span class=\"pl-en\">doStuff<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #148A14;\">\/*shouldCapitalize:*\/<\/span> <span style=\"color: #0000ff;\">false<\/span><span class=\"pl-kos\">)<\/span>\r\n<span class=\"pl-en\">doStuff<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #a31515;\">\"fee\"<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #a31515;\">\"fi\"<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #a31515;\">\"fo\"<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #a31515;\">\"fum\"<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #148A14;\">\/*shouldCapitalize:*\/<\/span> <span style=\"color: #0000ff;\">true<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>Even though JavaScript doesn&#8217;t have any syntax to model leading rest parameters, we were still able to declare <code>doStuff<\/code> as a function that takes leading arguments by declaring the <code>...args<\/code> rest parameter with <em>a tuple type that uses a leading rest element<\/em>. This can help model lots of existing JavaScript out there!<\/p>\n<p>For more details, <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/41544\">see the original pull request<\/a>.<\/p>\n<h2>Smarter Type Alias Preservation<\/h2>\n<p>TypeScript has always used a set of heuristics for when and how to display type aliases; but these techniques often have issues beyond simple uses. For example, take the following code snippet.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span class=\"pl-k\">export<\/span> <span class=\"pl-k\">type<\/span> <span style=\"color: #267F99;\">BasicPrimitive<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #0000ff;\">number<\/span> | <span style=\"color: #0000ff;\">string<\/span> | <span style=\"color: #0000ff;\">boolean<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span class=\"pl-k\">export<\/span> <span class=\"pl-k\">function<\/span> <span class=\"pl-en\">doStuff<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">value<\/span>: <span style=\"color: #267F99;\">BasicPrimitive<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-k\">let<\/span> <span class=\"pl-s1\">x<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">value<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-k\">return<\/span> <span class=\"pl-s1\">x<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>If we hover our mouse over <code>x<\/code> in an editor like Visual Studio, Visual Studio Code, or <a href=\"https:\/\/www.typescriptlang.org\/play?ts=4.1.3#code\/KYDwDg9gTgLgBDAnmYcBCBDAzgSwMYAKUOAtjjDgG6oC8cAdgK4kBGwUcAPnFjMfQHMucFhAgAbYBnoBuAFBzQkWHABmjengoR6cACYQAyjEarVACkoZxjYAC502fEVLkqwAJRwA3nLj+4SXgQODorG2B5ALgoYBMoXRB5AF8gA\" rel=\"nofollow\">the TypeScript Playground<\/a>, we&#8217;ll get a quick info panel that shows the type <code>BasicPrimitive<\/code>. Likewise, if we get the declaration file output (<code>.d.ts<\/code> output) for this file, TypeScript will say that <code>doStuff<\/code> returns <code>BasicPrimitive<\/code>.<\/p>\n<p>However, what happens if we return a <code>BasicPrimitive<\/code> or <code>undefined<\/code>?<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span class=\"pl-k\">export<\/span> <span class=\"pl-k\">type<\/span> <span style=\"color: #267F99;\">BasicPrimitive<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #0000ff;\">number<\/span> | <span style=\"color: #0000ff;\">string<\/span> | <span style=\"color: #0000ff;\">boolean<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span class=\"pl-k\">export<\/span> <span class=\"pl-k\">function<\/span> <span class=\"pl-en\">doStuff<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">value<\/span>: <span style=\"color: #267F99;\">BasicPrimitive<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-k\">if<\/span> <span class=\"pl-kos\">(<\/span><span style=\"color: #267F99;\">Math<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">random<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-c1\">&lt;<\/span> <span style=\"color: #09885A;\">0.5<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n        <span class=\"pl-k\">return<\/span> <span style=\"color: #0000ff;\">undefined<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-kos\">}<\/span>\r\n\r\n    <span class=\"pl-k\">return<\/span> <span class=\"pl-s1\">value<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>We can see what happens <a href=\"https:\/\/www.typescriptlang.org\/play?ts=4.1.3#code\/KYDwDg9gTgLgBDAnmYcBCBDAzgSwMYAKUOAtjjDgG6oC8cAdgK4kBGwUcAPnFjMfQHMucFhAgAbYBnoBuALAAoRQHplcABIRqHCPTgByACYQAyjEYAzC-pHBxEAO4IIPYKgcALDPAAqyYCZ4xGDwhjhYYOIYiFhwFtAIHqhQwOZQekgoAHQqagDqqGQCHvBe1HCgKHgwwIZw5M5wYPzw2Lm5cJ2YuITEZBTl3Iz0hsAWOPS1HR0sjPBs9k5+KIHB8AAsWQBMADT18BO8UnVhEVExcG0Kqh2dTKzswrz8QtyiElJ6QyNjE1PXykUlWg8Asw2qOF0cGMZksFgAFJQMOJGMAAFzobD4IikchUYAASjgAG9FJ1yTgLHB4QBZbweLJQaTGEjwokAHjgAAYsgBWImkhTk4WdFJpPTDUbjSaGeRC4UAX0UZOFYsY6TgSJRwDlcAVQA\" rel=\"nofollow\">in the TypeScript playground<\/a>. While we might want TypeScript to display the return type of <code>doStuff<\/code> as <code>BasicPrimitive | undefined<\/code>, it instead displays <code>string | number | boolean | undefined<\/code>! What gives?<\/p>\n<p>Well this has to do with how TypeScript represents types internally. When creating a union type out of one or more union types, it will always <em>normalize<\/em> those types into a new flattened union type &#8211; but doing that loses information. The type-checker didn&#8217;t have a way to know where that <code>string | number | boolean<\/code> had come from.<\/p>\n<p>In TypeScript 4.2, our internals are a little smarter. We keep track of how types were constructed by keeping around parts of their original structures &#8211; before we normalize them. We also keep track of, and differentiate, type aliases to instances of other aliases!<\/p>\n<p>Being able to print back the types based on how you used them in your code means that as a TypeScript user, you can avoid some unfortunately humongous types getting displayed, and that often translates to getting better <code>.d.ts<\/code> file output, error messages, and in-editor type displays in quick info and signature help.<\/p>\n<p>More more information, check out <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/42149\">the first pull request that improves various cases around preserving union type aliases<\/a>, along with <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/42284\">a second pull request that preserves indirect aliases<\/a>.<\/p>\n<h2>Template Literal Expressions Have Template Literal Types<\/h2>\n<p>In TypeScript 4.1, we introduced a new kind of type: template literal types. These types are able to model specific patterns of strings.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span class=\"pl-k\">type<\/span> <span style=\"color: #267F99;\">GreetingStart<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #a31515;\">\"hello\"<\/span> | <span style=\"color: #a31515;\">\"hi\"<\/span> | <span style=\"color: #a31515;\">\"sup\"<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span class=\"pl-k\">declare<\/span> <span class=\"pl-k\">function<\/span> <span class=\"pl-s1\">greet<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">str<\/span>: `${<span style=\"color: #267F99;\">GreetingStart<\/span><span class=\"pl-kos\">}<\/span> ${string<span class=\"pl-kos\">}<\/span>`<span class=\"pl-kos\">)<\/span>: <span class=\"pl-smi\"><span class=\"pl-k\">void<\/span><\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #148A14;\">\/\/ Works.<\/span>\r\n<span class=\"pl-en\">greet<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #a31515;\">\"hello world!\"<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #148A14;\">\/\/ Works.<\/span>\r\n<span class=\"pl-en\">greet<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #a31515;\">\"hi everybody!\"<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #148A14;\">\/\/ Error!<\/span>\r\n<span style=\"color: #148A14;\">\/\/ Doesn't work with any of the patterns:<\/span>\r\n<span style=\"color: #148A14;\">\/\/   `hello ${string}` | `hi ${string}` | `sup ${string}`<\/span>\r\n<span class=\"pl-en\">greet<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #a31515;\">\"hallo yes hi sup\"<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>However, in 4.1 there was a bit of a strange inconsistency between template string <em>types<\/em> and template string <em>expressions<\/em>.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span class=\"pl-k\">function<\/span> <span class=\"pl-en\">doStuff<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">str<\/span>: <span style=\"color: #0000ff;\">string<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #148A14;\">\/\/ Error!<\/span>\r\n    <span style=\"color: #148A14;\">\/\/ Type 'string' is not assignable to type '`hello ${string}`'.<\/span>\r\n    <span class=\"pl-k\">let<\/span> <span class=\"pl-s1\">x<\/span>: <span style=\"color: #a31515;\">`hello <span class=\"pl-s1\"><span class=\"pl-kos\">${<\/span>string<span class=\"pl-kos\">}<\/span><\/span>`<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #a31515;\">`hello <span class=\"pl-s1\"><span class=\"pl-kos\">${<\/span>str<span class=\"pl-kos\">}<\/span><\/span>`<\/span>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>This is because template string expressions with substitution slots <code>${likeThis}<\/code> have always just had the type <code>string<\/code>. In turn, those couldn&#8217;t be compatible with our new template string types.<\/p>\n<p>In TypeScript 4.2, template string expressions now always start out with template literal types. Similarly to string literal types, these types disappear and turn into <code>string<\/code> through a process called <em>widening<\/em> if we assign one of these values to a mutable variable.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span class=\"pl-k\">const<\/span> <span class=\"pl-s1\">n<\/span>: <span style=\"color: #0000ff;\">number<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #09885A;\">123<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #148A14;\">\/\/ Has the type `${number}px`<\/span>\r\n<span class=\"pl-k\">const<\/span> <span class=\"pl-s1\">s1<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #a31515;\">`<span class=\"pl-s1\"><span class=\"pl-kos\">${<\/span>n<span class=\"pl-kos\">}<\/span><\/span>px`<\/span><span class=\"pl-kos\">;<\/span>  \r\n\r\n<span style=\"color: #148A14;\">\/\/ Works!<\/span>\r\n<span class=\"pl-k\">const<\/span> <span class=\"pl-s1\">s2<\/span>: <span style=\"color: #a31515;\">`<span class=\"pl-s1\"><span class=\"pl-kos\">${<\/span>number<span class=\"pl-kos\">}<\/span><\/span>px`<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">s1<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #148A14;\">\/\/ Error!<\/span>\r\n<span class=\"pl-k\">const<\/span> <span class=\"pl-s1\">s3<\/span>: <span style=\"color: #a31515;\">`<span class=\"pl-s1\"><span class=\"pl-kos\">${<\/span>number<span class=\"pl-kos\">}<\/span><\/span>pt`<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">s1<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #148A14;\">\/\/ Has the type 'string' because of widening.<\/span>\r\n<span class=\"pl-k\">let<\/span> <span class=\"pl-s1\">v1<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">s1<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>You can <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/41891\">read up more at the implementing pull request<\/a>.<\/p>\n<h2>Stricter Checks for the <code>in<\/code> Operator<\/h2>\n<p>In JavaScript, it is a runtime error to use a non-object type on the right side of the <code>in<\/code> operator. TypeScript 4.2 ensures this can be caught at design-time.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #a31515;\">\"foo\"<\/span> <span class=\"pl-k\">in<\/span> <span style=\"color: #09885A;\">42<\/span>\r\n<span style=\"color: #148A14;\">\/\/       ~~<\/span>\r\n<span style=\"color: #148A14;\">\/\/ error! The right-hand side of an 'in' expression must not be a primitive.<\/span><\/pre>\n<\/div>\n<p>This check is fairly conservative for the most part, so if you have received an error about this, it is likely an issue in the code.<\/p>\n<p>A big thanks to our external contributor <a href=\"https:\/\/github.com\/jonhue\">Jonas H\u00fcbotter<\/a> for <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/41928\">their pull request<\/a>!<\/p>\n<h2><code>--noPropertyAccessFromIndexSignature<\/code><\/h2>\n<p>Back when TypeScript first introduced index signatures, you could only get properties declared by them with &#8220;bracketed&#8221; element access syntax like <code>person[\"name\"]<\/code>.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span class=\"pl-k\">interface<\/span> <span style=\"color: #267F99;\">SomeType<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #148A14;\">\/** This is an index signature. *\/<\/span>\r\n    <span class=\"pl-kos\">[<\/span><span class=\"pl-s1\">propName<\/span>: <span style=\"color: #0000ff;\">string<\/span><span class=\"pl-kos\">]<\/span>: <span style=\"color: #0000ff;\">any<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span class=\"pl-k\">function<\/span> <span class=\"pl-en\">doStuff<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">value<\/span>: <span style=\"color: #267F99;\">SomeType<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-k\">let<\/span> <span class=\"pl-s1\">x<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">value<\/span><span class=\"pl-kos\">[<\/span><span style=\"color: #a31515;\">\"someProperty\"<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>This ended up being cumbersome in situations where we need to work with objects that have arbitrary properties. For example, imagine an API where it&#8217;s common to misspell a property name by adding an extra <code>s<\/code> character at the end.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span class=\"pl-k\">interface<\/span> <span style=\"color: #267F99;\">Options<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #148A14;\">\/** File patterns to be excluded. *\/<\/span>\r\n    <span class=\"pl-c1\">exclude<\/span>?: <span style=\"color: #0000ff;\">string<\/span><span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n    <span style=\"color: #148A14;\">\/**<\/span>\r\n<span style=\"color: #148A14;\">     * It handles any extra properties that we haven't declared as type 'any'.<\/span>\r\n<span style=\"color: #148A14;\">     *\/<\/span>\r\n    <span class=\"pl-kos\">[<\/span><span class=\"pl-s1\">x<\/span>: <span style=\"color: #0000ff;\">string<\/span><span class=\"pl-kos\">]<\/span>: <span style=\"color: #0000ff;\">any<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span class=\"pl-k\">function<\/span> <span class=\"pl-en\">processOptions<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">opts<\/span>: <span style=\"color: #267F99;\">Options<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #148A14;\">\/\/ Notice we're *intentionally* accessing `excludes`, not `exclude`<\/span>\r\n    <span class=\"pl-k\">if<\/span> <span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">opts<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">excludes<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n        <span class=\"pl-smi\">console<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">error<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #a31515;\">\"The option `excludes` is not valid. Did you mean `exclude`?\"<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-kos\">}<\/span>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>To make these types of situations easier, a while back, TypeScript made it possible to use &#8220;dotted&#8221; property access syntax like <code>person.name<\/code> when a type had a string index signature. This also made it easier to transition existing JavaScript code over to TypeScript.<\/p>\n<p>However, loosening the restriction also meant that misspelling an explicitly declared property became much easier.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span class=\"pl-k\">function<\/span> <span class=\"pl-en\">processOptions<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">opts<\/span>: <span style=\"color: #267F99;\">Options<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #148A14;\">\/\/ ...<\/span>\r\n\r\n    <span style=\"color: #148A14;\">\/\/ Notice we're *accidentally* accessing `excludes` this time.<\/span>\r\n    <span style=\"color: #148A14;\">\/\/ Oops! Totally valid.<\/span>\r\n    <span class=\"pl-k\">for<\/span> <span class=\"pl-kos\">(<\/span><span class=\"pl-k\">const<\/span> <span class=\"pl-s1\">excludePattern<\/span> <span class=\"pl-k\">of<\/span> <span class=\"pl-s1\">opts<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">excludes<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n        <span style=\"color: #148A14;\">\/\/ ...<\/span>\r\n    <span class=\"pl-kos\">}<\/span>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>In some cases, users would prefer to explicitly opt into the index signature &#8211; they would prefer to get an error message when a dotted property access doesn&#8217;t correspond to a specific property declaration.<\/p>\n<p>That&#8217;s why TypeScript introduces a new flag called <code>--noPropertyAccessFromIndexSignature<\/code>. Under this mode, you&#8217;ll be opted in to TypeScript&#8217;s older behavior that issues an error. This new setting is not under the <code>strict<\/code> family of flags, since we believe users will find it more useful on certain codebases than others.<\/p>\n<p>You can understand this feature in more detail by reading up on the corresponding <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/40171\/\">pull request<\/a>. We&#8217;d also like to extend a big thanks to <a href=\"https:\/\/github.com\/Kingwl\">Wenlu Wang<\/a> who sent us this pull request!<\/p>\n<h2><code>abstract<\/code> Construct Signatures<\/h2>\n<p>TypeScript allows us to mark a class as <em>abstract<\/em>. This tells TypeScript that the class is only meant to be extended from, and that certain members need to be filled in by any subclass to actually create an instance.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span class=\"pl-k\">abstract<\/span> <span class=\"pl-k\">class<\/span> <span style=\"color: #267F99;\">Shape<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-k\">abstract<\/span> <span class=\"pl-c1\">getArea<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span>: <span style=\"color: #0000ff;\">number<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span style=\"color: #148A14;\">\/\/ Error! Can't instantiate an abstract class.<\/span>\r\n<span class=\"pl-k\">new<\/span> <span style=\"color: #267F99;\">Shape<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span class=\"pl-k\">class<\/span> <span style=\"color: #267F99;\">Square<\/span> <span class=\"pl-k\">extends<\/span> <span style=\"color: #267F99;\">Shape<\/span> <span class=\"pl-kos\">{<\/span>\r\n    #<span class=\"pl-c1\">sideLength<\/span>: <span style=\"color: #0000ff;\">number<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n    <span class=\"pl-en\">constructor<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">sideLength<\/span>: <span style=\"color: #0000ff;\">number<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n        <span style=\"color: #0000ff;\">this<\/span><span class=\"pl-kos\">.<\/span>#<span class=\"pl-c1\">sideLength<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">sideLength<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-kos\">}<\/span>\r\n\r\n    <span class=\"pl-en\">getArea<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n        <span class=\"pl-k\">return<\/span> <span style=\"color: #0000ff;\">this<\/span><span class=\"pl-kos\">.<\/span>#<span class=\"pl-c1\">sideLength<\/span> ** <span style=\"color: #09885A;\">2<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-kos\">}<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span style=\"color: #148A14;\">\/\/ Works fine.<\/span>\r\n<span class=\"pl-k\">new<\/span> <span style=\"color: #267F99;\">Square<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #09885A;\">42<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>To make sure this restriction in <code>new<\/code>-ing up <code>abstract<\/code> classes is consistently applied, you can&#8217;t assign an <code>abstract<\/code> class to anything that expects a construct signature.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span class=\"pl-k\">interface<\/span> <span style=\"color: #267F99;\">HasArea<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-c1\">getArea<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span>: <span style=\"color: #0000ff;\">number<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span style=\"color: #148A14;\">\/\/ Error! Cannot assign an abstract constructor type to a non-abstract constructor type.<\/span>\r\n<span class=\"pl-k\">let<\/span> <span style=\"color: #267F99;\">Ctor<\/span>: <span class=\"pl-k\">new<\/span> <span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-c1\">=&gt;<\/span> <span style=\"color: #267F99;\">HasArea<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #267F99;\">Shape<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>This does the right thing in case we intend to run code like <code>new Ctor<\/code>, but it&#8217;s overly-restrictive in case we want to write a subclass of <code>Ctor<\/code>.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span class=\"pl-s1\">functon<\/span> <span class=\"pl-en\">makeSubclassWithArea<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #267F99;\">Ctor<\/span>: <span class=\"pl-k\">new<\/span> <span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-c1\">=&gt;<\/span> <span style=\"color: #267F99;\">HasArea<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-k\">return<\/span> <span class=\"pl-k\">class<\/span> <span class=\"pl-k\">extends<\/span> <span style=\"color: #267F99;\">Ctor<\/span> <span class=\"pl-kos\">{<\/span>\r\n        <span class=\"pl-en\">getArea<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n            <span style=\"color: #148A14;\">\/\/ ...<\/span>\r\n        <span class=\"pl-kos\">}<\/span>\r\n    <span class=\"pl-kos\">}<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span class=\"pl-k\">let<\/span> <span style=\"color: #267F99;\">MyShape<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-en\">makeSubclassWithArea<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #267F99;\">Shape<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>It also doesn&#8217;t work well with built-in helper types like <code>InstanceType<\/code>.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #148A14;\">\/\/ Error!<\/span>\r\n<span style=\"color: #148A14;\">\/\/ Type 'typeof Shape' does not satisfy the constraint 'new (...args: any) =&gt; any'.<\/span>\r\n<span style=\"color: #148A14;\">\/\/   Cannot assign an abstract constructor type to a non-abstract constructor type.<\/span>\r\n<span class=\"pl-k\">type<\/span> <span style=\"color: #267F99;\">MyInstance<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #267F99;\">InstanceType<\/span><span class=\"pl-kos\">&lt;<\/span><span class=\"pl-k\">typeof<\/span> <span style=\"color: #267F99;\">Shape<\/span><span class=\"pl-kos\">&gt;<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>That&#8217;s why TypeScript 4.2 allows you to specify an <code>abstract<\/code> modifier on constructor signatures.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span class=\"pl-k\">interface<\/span> <span style=\"color: #267F99;\">HasArea<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-c1\">getArea<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span>: <span style=\"color: #0000ff;\">number<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span style=\"color: #148A14;\">\/\/ Works!<\/span>\r\n<span class=\"pl-k\">let<\/span> <span style=\"color: #267F99;\">Ctor<\/span>: <span class=\"pl-s1\">abstract<\/span> <span class=\"pl-k\">new<\/span> <span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-c1\">=&gt;<\/span> <span style=\"color: #267F99;\">HasArea<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #267F99;\">Shape<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #148A14;\">\/\/        ^^^^^^^^<\/span><\/pre>\n<\/div>\n<p>Adding the <code>abstract<\/code> modifier to a construct signature signals that you can pass in <code>abstract<\/code> constructors. It doesn&#8217;t stop you from passing in other classes\/constructor functions that are &#8220;concrete&#8221; &#8211; it really just signals that there&#8217;s no intent to run the constructor directly, so it&#8217;s safe to pass in either class type.<\/p>\n<p>This feature allows us to write <em>mixin factories<\/em> in a way that supports abstract classes. For example, in the following code snippet, we&#8217;re able to use the mixin function <code>withStyles<\/code> with the <code>abstract<\/code> class <code>SuperClass<\/code>.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span class=\"pl-k\">abstract<\/span> <span class=\"pl-k\">class<\/span> <span style=\"color: #267F99;\">SuperClass<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-k\">abstract<\/span> <span class=\"pl-c1\">someMethod<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-smi\"><span class=\"pl-k\">void<\/span><\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-en\">badda<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span><span class=\"pl-kos\">}<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span class=\"pl-k\">type<\/span> <span style=\"color: #267F99;\">AbstractConstructor<\/span><span class=\"pl-c1\">&lt;<\/span><span style=\"color: #267F99;\">T<\/span><span class=\"pl-c1\">&gt;<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">abstract<\/span> <span class=\"pl-k\">new<\/span> <span class=\"pl-kos\">(<\/span>...<span class=\"pl-s1\">args<\/span>: <span style=\"color: #0000ff;\">any<\/span><span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-c1\">=&gt;<\/span> <span style=\"color: #267F99;\">T<\/span>\r\n\r\n<span class=\"pl-k\">function<\/span> <span class=\"pl-en\">withStyles<\/span><span class=\"pl-c1\">&lt;<\/span><span style=\"color: #267F99;\">T<\/span> <span class=\"pl-k\">extends<\/span> <span style=\"color: #267F99;\">AbstractConstructor<\/span><span class=\"pl-kos\">&lt;<\/span><span style=\"color: #0000ff;\">object<\/span><span class=\"pl-kos\">&gt;<\/span><span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #267F99;\">Ctor<\/span>: <span style=\"color: #267F99;\">T<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-k\">abstract<\/span> <span class=\"pl-k\">class<\/span> <span style=\"color: #267F99;\">StyledClass<\/span> <span class=\"pl-k\">extends<\/span> <span style=\"color: #267F99;\">Ctor<\/span> <span class=\"pl-kos\">{<\/span>\r\n        <span class=\"pl-en\">getStyles<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n            <span style=\"color: #148A14;\">\/\/ ...<\/span>\r\n        <span class=\"pl-kos\">}<\/span>\r\n    <span class=\"pl-kos\">}<\/span>\r\n    <span class=\"pl-k\">return<\/span> <span style=\"color: #267F99;\">StyledClass<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span class=\"pl-k\">class<\/span> <span style=\"color: #267F99;\">SubClass<\/span> <span class=\"pl-k\">extends<\/span> <span class=\"pl-en\">withStyles<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #267F99;\">SuperClass<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-en\">someMethod<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n        <span style=\"color: #0000ff;\">this<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">someMethod<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span>\r\n    <span class=\"pl-kos\">}<\/span>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>Note that <code>withStyles<\/code> is demonstrating a specific rule, where a class (like <code>StyledClass<\/code>) that extends a value that&#8217;s generic and bounded by an abstract constructor (like <code>Ctor<\/code>) has to also be declared <code>abstract<\/code>. This is because there&#8217;s no way to know if a class with <em>more<\/em> abstract members was passed in, and so it&#8217;s impossible to know whether the subclass implements all the abstract members.<\/p>\n<p>You can read up more on abstract construct signatures <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/36392\">on its pull request<\/a>.<\/p>\n<h2><code>--explainFiles<\/code> to understand why files have been included in a program<\/h2>\n<p>A surprisingly common scenario for TypeScript users is to ask &#8220;why is TypeScript including this file?&#8221;. Inferring the files of your program turns out to be a complicated process, and so there are lots of reasons why a specific combination of <code>lib.d.ts<\/code> was used, why certain files in <code>node_modules<\/code> are getting included, and why certain files are being included even though we thought specifying <code>exclude<\/code> would keep them out.<\/p>\n<p>That&#8217;s why TypeScript now provides an <code>--explainFiles<\/code> flag.<\/p>\n<div class=\"highlight highlight-source-shell\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\">tsc --explainFiles<\/pre>\n<\/div>\n<p>When using this option, the TypeScript compiler will give some very verbose output about why a file ended up in your program. To read it more easily, you can forward the output to a file, or pipe it to a program that can easily view it.<\/p>\n<div class=\"highlight highlight-source-shell\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #148A14;\"># Forward output to a text file<\/span>\r\ntsc --explainFiles <span class=\"pl-k\">&gt;<\/span> expanation.txt\r\n\r\n<span style=\"color: #148A14;\"># Pipe output to a utility program like `less`, or an editor like VS Code<\/span>\r\ntsc --explainFiles <span class=\"pl-k\">|<\/span> less\r\n\r\ntsc --explainFiles <span class=\"pl-k\">|<\/span> code -<\/pre>\n<\/div>\n<p>Typically, the output will start out by listing out reasons for including <code>lib.d.ts<\/code> files, then for local files, and then <code>node_modules<\/code> files.<\/p>\n<pre><code>TS_Compiler_Directory\/4.2.0-beta\/lib\/lib.es5.d.ts\r\n  Library referenced via 'es5' from file 'TS_Compiler_Directory\/4.2.0-beta\/lib\/lib.es2015.d.ts'\r\nTS_Compiler_Directory\/4.2.0-beta\/lib\/lib.es2015.d.ts\r\n  Library referenced via 'es2015' from file 'TS_Compiler_Directory\/4.2.0-beta\/lib\/lib.es2016.d.ts'\r\nTS_Compiler_Directory\/4.2.0-beta\/lib\/lib.es2016.d.ts\r\n  Library referenced via 'es2016' from file 'TS_Compiler_Directory\/4.2.0-beta\/lib\/lib.es2017.d.ts'\r\nTS_Compiler_Directory\/4.2.0-beta\/lib\/lib.es2017.d.ts\r\n  Library referenced via 'es2017' from file 'TS_Compiler_Directory\/4.2.0-beta\/lib\/lib.es2018.d.ts'\r\nTS_Compiler_Directory\/4.2.0-beta\/lib\/lib.es2018.d.ts\r\n  Library referenced via 'es2018' from file 'TS_Compiler_Directory\/4.2.0-beta\/lib\/lib.es2019.d.ts'\r\nTS_Compiler_Directory\/4.2.0-beta\/lib\/lib.es2019.d.ts\r\n  Library referenced via 'es2019' from file 'TS_Compiler_Directory\/4.2.0-beta\/lib\/lib.es2020.d.ts'\r\nTS_Compiler_Directory\/4.2.0-beta\/lib\/lib.es2020.d.ts\r\n  Library referenced via 'es2020' from file 'TS_Compiler_Directory\/4.2.0-beta\/lib\/lib.esnext.d.ts'\r\nTS_Compiler_Directory\/4.2.0-beta\/lib\/lib.esnext.d.ts\r\n  Library 'lib.esnext.d.ts' specified in compilerOptions\r\n\r\n... More Library References...\r\n\r\nfoo.ts\r\n  Matched by include pattern '**\/*' in 'tsconfig.json'\r\n<\/code><\/pre>\n<p>Right now, we make no guarantees about the output format &#8211; it might change over time. On that note, we&#8217;re interested in improving this format if you have any suggestions!<\/p>\n<p>For more information, <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/40011\">check out the original pull request<\/a>!<\/p>\n<h2>Relaxed Rules Between Optional Properties and String Index Signatures<\/h2>\n<p>String index signatures are a way of typing dictionary-like objects, where you want to allow access with arbitrary keys:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span class=\"pl-k\">const<\/span> <span class=\"pl-s1\">movieWatchCount<\/span>: <span class=\"pl-kos\">{<\/span> <span class=\"pl-kos\">[<\/span><span class=\"pl-s1\">key<\/span>: <span style=\"color: #0000ff;\">string<\/span><span class=\"pl-kos\">]<\/span>: <span style=\"color: #0000ff;\">number<\/span> <span class=\"pl-kos\">}<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">{<\/span><span class=\"pl-kos\">}<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span class=\"pl-k\">function<\/span> <span class=\"pl-en\">watchMovie<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">title<\/span>: <span style=\"color: #0000ff;\">string<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n  <span class=\"pl-s1\">movieWatchCount<\/span><span class=\"pl-kos\">[<\/span><span class=\"pl-s1\">title<\/span><span class=\"pl-kos\">]<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">movieWatchCount<\/span><span class=\"pl-kos\">[<\/span><span class=\"pl-s1\">title<\/span><span class=\"pl-kos\">]<\/span> ?? <span style=\"color: #09885A;\">0<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-c1\">+<\/span> <span style=\"color: #09885A;\">1<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>Of course, for any movie title not yet in the dictionary, <code>movieWatchCount[title]<\/code> will be <code>undefined<\/code> (TypeScript 4.1 added the option <a href=\"https:\/\/www.typescriptlang.org\/docs\/handbook\/release-notes\/typescript-4-1.html#checked-indexed-accesses---nouncheckedindexedaccess\" rel=\"nofollow\"><code>--noUncheckedIndexedAccess<\/code><\/a> to include <code>undefined<\/code> when reading from an index signature like this). Even though it&#8217;s clear that there must be some strings not present in <code>movieWatchCount<\/code>, previous versions of TypeScript treated optional object properties as unassignable to otherwise compatible index signatures, due to the presence of <code>undefined<\/code>.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span class=\"pl-k\">type<\/span> <span style=\"color: #267F99;\">WesAndersonWatchCount<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">{<\/span>\r\n  <span style=\"color: #a31515;\">\"Fantastic Mr. Fox\"<\/span>?: <span style=\"color: #0000ff;\">number<\/span><span class=\"pl-kos\">;<\/span>\r\n  <span style=\"color: #a31515;\">\"The Royal Tenenbaums\"<\/span>?: <span style=\"color: #0000ff;\">number<\/span><span class=\"pl-kos\">;<\/span>\r\n  <span style=\"color: #a31515;\">\"Moonrise Kingdom\"<\/span>?: <span style=\"color: #0000ff;\">number<\/span><span class=\"pl-kos\">;<\/span>\r\n  <span style=\"color: #a31515;\">\"The Grand Budapest Hotel\"<\/span>?: <span style=\"color: #0000ff;\">number<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-kos\">}<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span class=\"pl-k\">declare<\/span> <span class=\"pl-k\">const<\/span> <span class=\"pl-s1\">wesAndersonWatchCount<\/span>: <span style=\"color: #267F99;\">WesAndersonWatchCount<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-k\">const<\/span> <span class=\"pl-s1\">movieWatchCount<\/span>: <span class=\"pl-kos\">{<\/span> <span class=\"pl-kos\">[<\/span><span class=\"pl-s1\">key<\/span>: <span style=\"color: #0000ff;\">string<\/span><span class=\"pl-kos\">]<\/span>: <span style=\"color: #0000ff;\">number<\/span> <span class=\"pl-kos\">}<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">wesAndersonWatchCount<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #148A14;\">\/\/    ~~~~~~~~~~~~~~~ error!<\/span>\r\n<span style=\"color: #148A14;\">\/\/ Type 'WesAndersonWatchCount' is not assignable to type '{ [key: string]: number; }'.<\/span>\r\n<span style=\"color: #148A14;\">\/\/    Property '\"Fantastic Mr. Fox\"' is incompatible with index signature.<\/span>\r\n<span style=\"color: #148A14;\">\/\/      Type 'number | undefined' is not assignable to type 'number'.<\/span>\r\n<span style=\"color: #148A14;\">\/\/        Type 'undefined' is not assignable to type 'number'. (2322)<\/span><\/pre>\n<\/div>\n<p>TypeScript 4.2 allows this assignment. However, it does <em>not<\/em> allow the assignment of non-optional properties with <code>undefined<\/code> in their types, nor does it allow writing <code>undefined<\/code> to a specific key:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span class=\"pl-k\">type<\/span> <span style=\"color: #267F99;\">BatmanWatchCount<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">{<\/span>\r\n  <span style=\"color: #a31515;\">\"Batman Begins\"<\/span>: <span style=\"color: #0000ff;\">number<\/span> | <span style=\"color: #0000ff;\">undefined<\/span><span class=\"pl-kos\">;<\/span>\r\n  <span style=\"color: #a31515;\">\"The Dark Knight\"<\/span>: <span style=\"color: #0000ff;\">number<\/span> | <span style=\"color: #0000ff;\">undefined<\/span><span class=\"pl-kos\">;<\/span>\r\n  <span style=\"color: #a31515;\">\"The Dark Knight Rises\"<\/span>: <span style=\"color: #0000ff;\">number<\/span> | <span style=\"color: #0000ff;\">undefined<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-kos\">}<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span class=\"pl-k\">declare<\/span> <span class=\"pl-k\">const<\/span> <span class=\"pl-s1\">batmanWatchCount<\/span>: <span style=\"color: #267F99;\">BatmanWatchCount<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #148A14;\">\/\/ Still an error in TypeScript 4.2.<\/span>\r\n<span style=\"color: #148A14;\">\/\/ `undefined` is only ignored when properties are marked optional.<\/span>\r\n<span class=\"pl-k\">const<\/span> <span class=\"pl-s1\">movieWatchCount<\/span>: <span class=\"pl-kos\">{<\/span> <span class=\"pl-kos\">[<\/span><span class=\"pl-s1\">key<\/span>: <span style=\"color: #0000ff;\">string<\/span><span class=\"pl-kos\">]<\/span>: <span style=\"color: #0000ff;\">number<\/span> <span class=\"pl-kos\">}<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">batmanWatchCount<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #148A14;\">\/\/ Still an error in TypeScript 4.2.<\/span>\r\n<span style=\"color: #148A14;\">\/\/ Index signatures don't implicitly allow explicit `undefined`.<\/span>\r\n<span class=\"pl-s1\">movieWatchCount<\/span><span class=\"pl-kos\">[<\/span><span style=\"color: #a31515;\">\"It's the Great Pumpkin, Charlie Brown\"<\/span><span class=\"pl-kos\">]<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #0000ff;\">undefined<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>The new rule also does not apply to number index signatures, since they are assumed to be array-like and dense:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span class=\"pl-k\">declare<\/span> <span class=\"pl-k\">let<\/span> <span class=\"pl-s1\">sortOfArrayish<\/span>: <span class=\"pl-kos\">{<\/span> <span class=\"pl-kos\">[<\/span><span class=\"pl-s1\">key<\/span>: <span style=\"color: #0000ff;\">number<\/span><span class=\"pl-kos\">]<\/span>: <span style=\"color: #0000ff;\">string<\/span> <span class=\"pl-kos\">}<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-k\">declare<\/span> <span class=\"pl-k\">let<\/span> <span class=\"pl-s1\">numberKeys<\/span>: <span class=\"pl-kos\">{<\/span> <span style=\"color: #09885A;\">42<\/span>?: <span style=\"color: #0000ff;\">string<\/span> <span class=\"pl-kos\">}<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #148A14;\">\/\/ Error! Type '{ 42?: string | undefined; }' is not assignable to type '{ [key: number]: string; }'.<\/span>\r\n<span class=\"pl-s1\">sortOfArrayish<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">numberKeys<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>You can get a better sense of this change <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/41921\">by reading up on the original PR<\/a>.<\/p>\n<h2>Declare Missing Helper Function<\/h2>\n<p>Thanks to <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/41215\">a community pull request<\/a> from <a href=\"https:\/\/github.com\/a-tarasyuk\">Alexander Tarasyuk<\/a>, we now have a quick fix for declaring new functions and methods based on the call-site!<\/p>\n<p><img decoding=\"async\" alt=\"An un-declared function foo being called, with a quick fix scaffolding out the new contents of the file\" src=\"https:\/\/devblogs.microsoft.com\/typescript\/wp-content\/uploads\/sites\/11\/2021\/01\/addMissingFunction-4.2.gif\" \/><\/p>\n<h2>Breaking Changes<\/h2>\n<p>We always strive to minimize breaking changes in a release. TypeScript 4.2 contains some breaking changes, but we believe they should be manageable in an upgrade.<\/p>\n<h3>Template Literal Expressions Have Template Literal Types<\/h3>\n<p>As mentioned previously, template string expressions now start out with template literal types.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span class=\"pl-k\">const<\/span> <span class=\"pl-s1\">n<\/span>: <span style=\"color: #0000ff;\">number<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #09885A;\">123<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-k\">const<\/span> <span class=\"pl-s1\">s1<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #a31515;\">`<span class=\"pl-s1\"><span class=\"pl-kos\">${<\/span>n<span class=\"pl-kos\">}<\/span><\/span>px`<\/span><span class=\"pl-kos\">;<\/span>  <span style=\"color: #148A14;\">\/\/ `${number}px`<\/span>\r\n<span class=\"pl-k\">const<\/span> <span class=\"pl-s1\">s2<\/span>: <span style=\"color: #a31515;\">`<span class=\"pl-s1\"><span class=\"pl-kos\">${<\/span>number<span class=\"pl-kos\">}<\/span><\/span>px`<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">s1<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-k\">const<\/span> <span class=\"pl-s1\">s3<\/span>: <span style=\"color: #a31515;\">`<span class=\"pl-s1\"><span class=\"pl-kos\">${<\/span>number<span class=\"pl-kos\">}<\/span><\/span>pt`<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">s1<\/span><span class=\"pl-kos\">;<\/span>  <span style=\"color: #148A14;\">\/\/ Error<\/span>\r\n<span class=\"pl-k\">let<\/span> <span class=\"pl-s1\">v1<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">s1<\/span><span class=\"pl-kos\">;<\/span>  <span style=\"color: #148A14;\">\/\/ string (because of widening)<\/span><\/pre>\n<\/div>\n<p>This is a break, as these values used to just have the type <code>string<\/code>.<\/p>\n<p><a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/41891\">See the respective pull request for more details<\/a>.<\/p>\n<h3><code>noImplicitAny<\/code> Errors Apply to Loose <code>yield<\/code> Expressions<\/h3>\n<p>When a <code>yield<\/code> expression is captured, but isn&#8217;t contextually typed (i.e. TypeScript can&#8217;t figure out what the type is), TypeScript will now issue an implicit <code>any<\/code> error.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span class=\"pl-k\">function<\/span>* <span class=\"pl-s1\">g1<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n  <span class=\"pl-k\">const<\/span> <span class=\"pl-s1\">value<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-k\">yield<\/span> <span style=\"color: #09885A;\">1<\/span><span class=\"pl-kos\">;<\/span> <span style=\"color: #148A14;\">\/\/ report implicit any error<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span class=\"pl-k\">function<\/span>* <span class=\"pl-s1\">g2<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n  <span class=\"pl-k\">yield<\/span> <span style=\"color: #09885A;\">1<\/span><span class=\"pl-kos\">;<\/span> <span style=\"color: #148A14;\">\/\/ result is unused, no error<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span class=\"pl-k\">function<\/span>* <span class=\"pl-s1\">g3<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n  <span class=\"pl-k\">const<\/span> <span class=\"pl-s1\">value<\/span>: <span style=\"color: #0000ff;\">string<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-k\">yield<\/span> <span style=\"color: #09885A;\">1<\/span><span class=\"pl-kos\">;<\/span> <span style=\"color: #148A14;\">\/\/ result is contextually typed by type annotation of `value`, no error.<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span class=\"pl-k\">function<\/span>* <span class=\"pl-s1\">g3<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span>: <span style=\"color: #267F99;\">Generator<\/span><span class=\"pl-kos\">&lt;<\/span><span style=\"color: #0000ff;\">number<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-smi\"><span class=\"pl-k\">void<\/span><\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #0000ff;\">string<\/span><span class=\"pl-kos\">&gt;<\/span> <span class=\"pl-kos\">{<\/span>\r\n  <span class=\"pl-k\">const<\/span> <span class=\"pl-s1\">value<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-k\">yield<\/span> <span style=\"color: #09885A;\">1<\/span><span class=\"pl-kos\">;<\/span> <span style=\"color: #148A14;\">\/\/ result is contextually typed by return-type annotation of `g3`, no error.<\/span>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>See more details in <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/41348\">the corresponding changes<\/a>.<\/p>\n<h3>Type Arguments in JavaScript Are Not Parsed as Type Arguments<\/h3>\n<p>Type arguments were already not allowed in JavaScript, but in TypeScript 4.2, the parser will parse them in a more spec-compliant way. So when writing the following code in a JavaScript file:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span class=\"pl-en\">f<\/span><span class=\"pl-kos\">&lt;<\/span><span style=\"color: #267F99;\">T<\/span><span class=\"pl-kos\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #09885A;\">100<\/span><span class=\"pl-kos\">)<\/span><\/pre>\n<\/div>\n<p>TypeScript will parse it as the following JavaScript:<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">f<\/span> <span class=\"pl-c1\">&lt;<\/span> <span class=\"pl-v\">T<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-c1\">&gt;<\/span> <span class=\"pl-kos\">(<\/span><span style=\"color: #09885A;\">100<\/span><span class=\"pl-kos\">)<\/span><\/pre>\n<\/div>\n<p>This may impact you if you were leveraging TypeScript&#8217;s API to parse type constructs in JavaScript files, which may have occurred when trying to parse Flow files.<\/p>\n<h2>The <code>in<\/code> Operator No Longer Allows Primitive Types on the Right Side<\/h2>\n<p>As mentioned, it is an error to use a primitive on the right side of an <code>in<\/code> operator, and TypeScript 4.2 is stricter about this sort of code.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #a31515;\">\"foo\"<\/span> <span class=\"pl-k\">in<\/span> <span style=\"color: #09885A;\">42<\/span>\r\n<span style=\"color: #148A14;\">\/\/       ~~<\/span>\r\n<span style=\"color: #148A14;\">\/\/ error! The right-hand side of an 'in' expression must not be a primitive.<\/span><\/pre>\n<\/div>\n<p>See <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/41928\">the pull request<\/a> for more details on what&#8217;s checked.<\/p>\n<h2>TypeScript&#8217;s <code>lift<\/code> Callback in <code>visitNode<\/code> Uses a Different Type<\/h2>\n<p>TypeScript has a <code>visitNode<\/code> function that takes a <code>lift<\/code> function. <code>lift<\/code> now expects a <code>readonly Node[]<\/code> instead of a <code>NodeArray&lt;Node&gt;<\/code>. This is technically an API breaking change which you can read more on <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/42000\">here<\/a>.<\/p>\n<h2>What&#8217;s Next?<\/h2>\n<p>We&#8217;re excited to hear your thoughts on TypeScript 4.2! With the beta we&#8217;re still in relatively early stages, but we&#8217;re counting on your feedback to help make this an excellent release. So try it today, and <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/issues\">let us know if you run into anything<\/a>!<\/p>\n<p>Happy Hacking!<\/p>\n<p>&#8211; Daniel Rosenwasser and the TypeScript Team<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today we&#8217;re excited to announce the availability of TypeScript 4.2 Beta! To get started using the beta, you can get it through NuGet, or use npm with the following command: npm install typescript@beta You can also get editor support by Downloading for Visual Studio 2019\/2017 Following directions for Visual Studio Code and Sublime Text. Let&#8217;s [&hellip;]<\/p>\n","protected":false},"author":381,"featured_media":1797,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-2846","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-typescript"],"acf":[],"blog_post_summary":"<p>Today we&#8217;re excited to announce the availability of TypeScript 4.2 Beta! To get started using the beta, you can get it through NuGet, or use npm with the following command: npm install typescript@beta You can also get editor support by Downloading for Visual Studio 2019\/2017 Following directions for Visual Studio Code and Sublime Text. Let&#8217;s [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/2846","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/users\/381"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/comments?post=2846"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/2846\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/media\/1797"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/media?parent=2846"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/categories?post=2846"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/tags?post=2846"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}