{"id":116976,"date":"2020-08-20T16:52:00","date_gmt":"2020-08-20T16:52:00","guid":{"rendered":"https:\/\/news.microsoft.com\/?p=438785"},"modified":"2020-08-20T16:52:00","modified_gmt":"2020-08-20T16:52:00","slug":"developers-learn-whats-new-in-typescript-4-0","status":"publish","type":"post","link":"https:\/\/sickgaming.net\/blog\/2020\/08\/20\/developers-learn-whats-new-in-typescript-4-0\/","title":{"rendered":"Developers: Learn what\u2019s new in TypeScript 4.0"},"content":{"rendered":"<div class=\"row justify-content-center\">\n<div class=\"col-md-4\">\n<div><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2020\/08\/developers-learn-whats-new-in-typescript-4-0.jpg\" width=\"58\" height=\"58\" alt=\"Avatar\" class=\"avatar avatar-58 wp-user-avatar wp-user-avatar-58 photo avatar-default\"><\/p>\n<p>Daniel<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"entry-meta entry-meta-layout\">\n<p>August 20th, 2020<\/p>\n<\/div>\n<p>Today we are thrilled to announce the availability of TypeScript 4.0! This version of the language represents our next generation of TypeScript releases, as we dive deeper into expressivity, productivity, and scalability.<\/p>\n<p>If you\u2019re not familiar with TypeScript, it\u2019s a language that builds on top of JavaScript by adding syntax for <em>static types<\/em>. The idea is that by writing down the types of your values and where they\u2019re used, you can use TypeScript to type-check your code and tell you about mistakes before you run your code (and even before saving your file). You can then use the TypeScript compiler to then strip away types from your code, and leaving you with clean, readable JavaScript that runs anywhere. Beyond checking, TypeScript also uses static types to power great editor tooling like auto-completion, code navigation, refactorings, and more. In fact, if you\u2019ve used JavaScript in an editor like Visual Studio Code or Visual Studio, you\u2019ve already been using an experience powered by types and TypeScript. You can <a href=\"https:\/\/www.typescriptlang.org\/\" rel=\"nofollow\">learn more about all of this on our website<\/a>.<\/p>\n<p>With TypeScript 4.0, there are no major breaking changes. In fact, if you\u2019re new to the language, now is the best time to start using it. The community is already here and growing, with working code and great new resources to learn. And one thing to keep in mind: despite all the good stuff we\u2019re bringing in 4.0, you really only need to know the basics of TypeScript to be productive!<\/p>\n<p>If you\u2019re already using TypeScript in your project, you can either 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\">npm install -D typescript<\/pre>\n<\/div>\n<p>You can also get editor support by<\/p>\n<p>TypeScript is a core part of many people\u2019s JavaScript stack today. On npm, TypeScript saw over 50 million monthly downloads for the first time in July! And while we recognize there\u2019s always room for growth and improvement, it\u2019s clear that most people coding in TypeScript really do enjoy it. StackOverflow\u2019s most recent developer survey pins <a href=\"https:\/\/insights.stackoverflow.com\/survey\/2020#technology-most-loved-dreaded-and-wanted-languages\" rel=\"nofollow\">TypeScript as the 2nd most-loved language<\/a>. In the most recent State of JS Survey, <a href=\"https:\/\/2019.stateofjs.com\/javascript-flavors\/typescript\/\" rel=\"nofollow\">around 89% of developers who used TypeScript said that they would use it again<\/a>.<\/p>\n<p>It\u2019s worth digging a bit into how we got here. In our past two major versions, we looked back at some highlights that shined over the years. For TypeScript 4.0, we\u2019re going to keep up that tradition.<\/p>\n<p>Looking back from 3.0 onward, there\u2019s a dizzying number of changes, but <a href=\"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-3-0\/\" rel=\"nofollow\">TypeScript 3.0<\/a> itself came out with a punch. Unifying tuple types and parameter lists was a big highlight, enabling tons of existing JavaScript patterns on functions. The release also featured project references to help scale up, organize, and share across codebases. One small change that had a big impact was that 3.0 introduced a type-safe alternative to <code>any<\/code> called <code>unknown<\/code>.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-3-1\/\" rel=\"nofollow\">TypeScript 3.1<\/a> extended the capabilities of <a href=\"https:\/\/www.typescriptlang.org\/docs\/handbook\/advanced-types.html#mapped-types\" rel=\"nofollow\">mapped types<\/a> to work on tuple and array types, and made it dramatically easier to attach properties to functions without resorting to TypeScript-specific runtime features that have fallen out of use.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-3-2\/\" rel=\"nofollow\">TypeScript 3.2<\/a> allowed object spreads on generic types, and leveraged 3.0\u2019s capabilities to better model meta-programming with functions by strictly typing <code>bind<\/code>, <code>call<\/code>, and <code>apply<\/code>. <a href=\"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-3-3\/\" rel=\"nofollow\">TypeScript 3.3<\/a> focused a bit on stability following 3.2, but also brought quality-of-life improvements when using union type methods, and added file-incremental builds under <code>--build<\/code> mode.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-3-4\/\" rel=\"nofollow\">In the 3.4 release<\/a>, we leaned farther into supporting functional patterns, with better support for immutable data structures, and improved inference on higher-order generic functions. As a big plus, this release introduced the <code>--incremental<\/code> flag, a way to get faster compiles and type-checks by avoiding a full rebuild on every run of TypeScript, without project references.<\/p>\n<p>With <a href=\"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-3-5\/\" rel=\"nofollow\">TypeScript 3.5<\/a> and <a href=\"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-3-6\/\" rel=\"nofollow\">3.6<\/a>, we saw some tightening up of the type system rules, along with smarter compatibility checking rules.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-3-7\/\" rel=\"nofollow\">TypeScript 3.7<\/a> was a very noteworthy release because it featured a rich combination of new type system features with ECMAScript features. From the type-system side, we saw recursive type alias references and support for assertion-style functions, both which are unique type-system features. From the JavaScript side, the release brought optional chaining and coalescing, two of the most highly demanded features for TypeScript and JavaScript users alike, championed in TC39 in part by our team.<\/p>\n<p>Much more recently, <a href=\"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-3-8\/\" rel=\"nofollow\">3.8<\/a> and <a href=\"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-3-9\/\" rel=\"nofollow\">3.9<\/a> have brought type-only imports\/exports, along with ECMAScript features like private fields, top-level <code>await<\/code> in modules, and new <code>export *<\/code> syntaxes. These releases also delivered performance and scalability optimizations.<\/p>\n<p>We haven\u2019t even touched on all the work in our language service, our infrastructure, our website, and other core projects which are incredibly valuable to the TypeScript experience. Beyond the core team\u2019s projects is the incredible community of contributors in the ecosystem, pushing the experience forward, and helping out with DefinitelyTyped and even TypeScript itself. DefinitelyTyped had just 80 pull requests in 2012 when it first started, picking up on the tail end of the year. In 2019, it had <em>over 8300 pull requests<\/em>, which still astounds us. These contributions are fundamental to the TypeScript experience, so we\u2019re grateful for such a bustling and eager community that\u2019s been improving the ecosystem and pushed us to constantly improve.<\/p>\n<h2 id=\"whats-new\">What\u2019s New?<\/h2>\n<p>All this brings us to 4.0! So, without further ado, let\u2019s dive into what\u2019s new!<\/p>\n<h2 id=\"variadic-tuple-types\">Variadic Tuple Types<\/h2>\n<p>Consider a function in JavaScript called <code>concat<\/code> that takes two array or tuple types and concatenates them together to make a new array.<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\"><span>function<\/span> <span class=\"pl-en\">concat<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">arr2<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span> <span>return<\/span> <span class=\"pl-kos\">[<\/span>...<span class=\"pl-s1\">arr1<\/span><span class=\"pl-kos\">,<\/span> ...<span class=\"pl-s1\">arr2<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>Also consider <code>tail<\/code>, that takes an array or tuple, and returns all elements but the first.<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\"><span>function<\/span> <span class=\"pl-en\">tail<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arg<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span> <span>const<\/span> <span class=\"pl-kos\">[<\/span><span class=\"pl-s1\">_<\/span><span class=\"pl-kos\">,<\/span> ...<span class=\"pl-s1\">result<\/span><span class=\"pl-kos\">]<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">arg<\/span><span class=\"pl-kos\">;<\/span> <span>return<\/span> <span class=\"pl-s1\">result<\/span>\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>How would we type either of these in TypeScript?<\/p>\n<p>For <code>concat<\/code>, the only valid thing we could do in older versions of the language was to try and write some overloads.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">arr2<\/span>: <span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\n<span>function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span><span>A<\/span><span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span class=\"pl-kos\">[<\/span><span>A<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">arr2<\/span>: <span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-kos\">[<\/span><span>A<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\n<span>function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span><span>A<\/span><span class=\"pl-kos\">,<\/span> <span>B<\/span><span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span class=\"pl-kos\">[<\/span><span>A<\/span><span class=\"pl-kos\">,<\/span> <span>B<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">arr2<\/span>: <span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-kos\">[<\/span><span>A<\/span><span class=\"pl-kos\">,<\/span> <span>B<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\n<span>function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span><span>A<\/span><span class=\"pl-kos\">,<\/span> <span>B<\/span><span class=\"pl-kos\">,<\/span> <span>C<\/span><span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span class=\"pl-kos\">[<\/span><span>A<\/span><span class=\"pl-kos\">,<\/span> <span>B<\/span><span class=\"pl-kos\">,<\/span> <span>C<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">arr2<\/span>: <span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-kos\">[<\/span><span>A<\/span><span class=\"pl-kos\">,<\/span> <span>B<\/span><span class=\"pl-kos\">,<\/span> <span>C<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\n<span>function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span><span>A<\/span><span class=\"pl-kos\">,<\/span> <span>B<\/span><span class=\"pl-kos\">,<\/span> <span>C<\/span><span class=\"pl-kos\">,<\/span> <span>D<\/span><span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span class=\"pl-kos\">[<\/span><span>A<\/span><span class=\"pl-kos\">,<\/span> <span>B<\/span><span class=\"pl-kos\">,<\/span> <span>C<\/span><span class=\"pl-kos\">,<\/span> <span>D<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">arr2<\/span>: <span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-kos\">[<\/span><span>A<\/span><span class=\"pl-kos\">,<\/span> <span>B<\/span><span class=\"pl-kos\">,<\/span> <span>C<\/span><span class=\"pl-kos\">,<\/span> <span>D<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\n<span>function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span><span>A<\/span><span class=\"pl-kos\">,<\/span> <span>B<\/span><span class=\"pl-kos\">,<\/span> <span>C<\/span><span class=\"pl-kos\">,<\/span> <span>D<\/span><span class=\"pl-kos\">,<\/span> <span>E<\/span><span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span class=\"pl-kos\">[<\/span><span>A<\/span><span class=\"pl-kos\">,<\/span> <span>B<\/span><span class=\"pl-kos\">,<\/span> <span>C<\/span><span class=\"pl-kos\">,<\/span> <span>D<\/span><span class=\"pl-kos\">,<\/span> <span>E<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">arr2<\/span>: <span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-kos\">[<\/span><span>A<\/span><span class=\"pl-kos\">,<\/span> <span>B<\/span><span class=\"pl-kos\">,<\/span> <span>C<\/span><span class=\"pl-kos\">,<\/span> <span>D<\/span><span class=\"pl-kos\">,<\/span> <span>E<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\n<span>function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span><span>A<\/span><span class=\"pl-kos\">,<\/span> <span>B<\/span><span class=\"pl-kos\">,<\/span> <span>C<\/span><span class=\"pl-kos\">,<\/span> <span>D<\/span><span class=\"pl-kos\">,<\/span> <span>E<\/span><span class=\"pl-kos\">,<\/span> <span>F<\/span><span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span class=\"pl-kos\">[<\/span><span>A<\/span><span class=\"pl-kos\">,<\/span> <span>B<\/span><span class=\"pl-kos\">,<\/span> <span>C<\/span><span class=\"pl-kos\">,<\/span> <span>D<\/span><span class=\"pl-kos\">,<\/span> <span>E<\/span><span class=\"pl-kos\">,<\/span> <span>F<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">arr2<\/span>: <span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-kos\">[<\/span><span>A<\/span><span class=\"pl-kos\">,<\/span> <span>B<\/span><span class=\"pl-kos\">,<\/span> <span>C<\/span><span class=\"pl-kos\">,<\/span> <span>D<\/span><span class=\"pl-kos\">,<\/span> <span>E<\/span><span class=\"pl-kos\">,<\/span> <span>F<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span><span class=\"pl-kos\">)<\/span><\/pre>\n<\/div>\n<p>Uh\u2026okay, that\u2019s\u2026seven overloads for when the second array is always empty. Let\u2019s add some for when <code>arr2<\/code> has one argument.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span><span>A2<\/span><span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">arr2<\/span>: <span class=\"pl-kos\">[<\/span><span>A2<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-kos\">[<\/span><span>A2<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\n<span>function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span><span>A1<\/span><span class=\"pl-kos\">,<\/span> <span>A2<\/span><span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span class=\"pl-kos\">[<\/span><span>A1<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">arr2<\/span>: <span class=\"pl-kos\">[<\/span><span>A2<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-kos\">[<\/span><span>A1<\/span><span class=\"pl-kos\">,<\/span> <span>A2<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\n<span>function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span><span>A1<\/span><span class=\"pl-kos\">,<\/span> <span>B1<\/span><span class=\"pl-kos\">,<\/span> <span>A2<\/span><span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span class=\"pl-kos\">[<\/span><span>A1<\/span><span class=\"pl-kos\">,<\/span> <span>B1<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">arr2<\/span>: <span class=\"pl-kos\">[<\/span><span>A2<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-kos\">[<\/span><span>A1<\/span><span class=\"pl-kos\">,<\/span> <span>B1<\/span><span class=\"pl-kos\">,<\/span> <span>A2<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\n<span>function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span><span>A1<\/span><span class=\"pl-kos\">,<\/span> <span>B1<\/span><span class=\"pl-kos\">,<\/span> <span>C1<\/span><span class=\"pl-kos\">,<\/span> <span>A2<\/span><span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span class=\"pl-kos\">[<\/span><span>A1<\/span><span class=\"pl-kos\">,<\/span> <span>B1<\/span><span class=\"pl-kos\">,<\/span> <span>C1<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">arr2<\/span>: <span class=\"pl-kos\">[<\/span><span>A2<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-kos\">[<\/span><span>A1<\/span><span class=\"pl-kos\">,<\/span> <span>B1<\/span><span class=\"pl-kos\">,<\/span> <span>C1<\/span><span class=\"pl-kos\">,<\/span> <span>A2<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\n<span>function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span><span>A1<\/span><span class=\"pl-kos\">,<\/span> <span>B1<\/span><span class=\"pl-kos\">,<\/span> <span>C1<\/span><span class=\"pl-kos\">,<\/span> <span>D1<\/span><span class=\"pl-kos\">,<\/span> <span>A2<\/span><span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span class=\"pl-kos\">[<\/span><span>A1<\/span><span class=\"pl-kos\">,<\/span> <span>B1<\/span><span class=\"pl-kos\">,<\/span> <span>C1<\/span><span class=\"pl-kos\">,<\/span> <span>D1<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">arr2<\/span>: <span class=\"pl-kos\">[<\/span><span>A2<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-kos\">[<\/span><span>A1<\/span><span class=\"pl-kos\">,<\/span> <span>B1<\/span><span class=\"pl-kos\">,<\/span> <span>C1<\/span><span class=\"pl-kos\">,<\/span> <span>D1<\/span><span class=\"pl-kos\">,<\/span> <span>A2<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\n<span>function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span><span>A1<\/span><span class=\"pl-kos\">,<\/span> <span>B1<\/span><span class=\"pl-kos\">,<\/span> <span>C1<\/span><span class=\"pl-kos\">,<\/span> <span>D1<\/span><span class=\"pl-kos\">,<\/span> <span>E1<\/span><span class=\"pl-kos\">,<\/span> <span>A2<\/span><span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span class=\"pl-kos\">[<\/span><span>A1<\/span><span class=\"pl-kos\">,<\/span> <span>B1<\/span><span class=\"pl-kos\">,<\/span> <span>C1<\/span><span class=\"pl-kos\">,<\/span> <span>D1<\/span><span class=\"pl-kos\">,<\/span> <span>E1<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">arr2<\/span>: <span class=\"pl-kos\">[<\/span><span>A2<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-kos\">[<\/span><span>A1<\/span><span class=\"pl-kos\">,<\/span> <span>B1<\/span><span class=\"pl-kos\">,<\/span> <span>C1<\/span><span class=\"pl-kos\">,<\/span> <span>D1<\/span><span class=\"pl-kos\">,<\/span> <span>E1<\/span><span class=\"pl-kos\">,<\/span> <span>A2<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\n<span>function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span><span>A1<\/span><span class=\"pl-kos\">,<\/span> <span>B1<\/span><span class=\"pl-kos\">,<\/span> <span>C1<\/span><span class=\"pl-kos\">,<\/span> <span>D1<\/span><span class=\"pl-kos\">,<\/span> <span>E1<\/span><span class=\"pl-kos\">,<\/span> <span>F1<\/span><span class=\"pl-kos\">,<\/span> <span>A2<\/span><span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span class=\"pl-kos\">[<\/span><span>A1<\/span><span class=\"pl-kos\">,<\/span> <span>B1<\/span><span class=\"pl-kos\">,<\/span> <span>C1<\/span><span class=\"pl-kos\">,<\/span> <span>D1<\/span><span class=\"pl-kos\">,<\/span> <span>E1<\/span><span class=\"pl-kos\">,<\/span> <span>F1<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">arr2<\/span>: <span class=\"pl-kos\">[<\/span><span>A2<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-kos\">[<\/span><span>A1<\/span><span class=\"pl-kos\">,<\/span> <span>B1<\/span><span class=\"pl-kos\">,<\/span> <span>C1<\/span><span class=\"pl-kos\">,<\/span> <span>D1<\/span><span class=\"pl-kos\">,<\/span> <span>E1<\/span><span class=\"pl-kos\">,<\/span> <span>F1<\/span><span class=\"pl-kos\">,<\/span> <span>A2<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>We hope it\u2019s clear that this is getting unreasonable. Unfortunately, you\u2019d also end up with the same sorts of issues typing a function like <code>tail<\/code>.<\/p>\n<p>This is another case of what we like to call \u201cdeath by a thousand overloads\u201d, and it doesn\u2019t even solve the problem generally. It only gives correct types for as many overloads as we care to write. If we wanted to make a catch-all case, we\u2019d need an overload like the following:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span><span>T<\/span><span class=\"pl-kos\">,<\/span> <span>U<\/span><span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span>T<\/span><span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">arr2<\/span>: <span>U<\/span><span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: <span>Array<\/span><span class=\"pl-kos\">&lt;<\/span><span>T<\/span> | <span>U<\/span><span class=\"pl-kos\">&gt;<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>But that signature doesn\u2019t encode anything about the lengths of the input, or the order of the elements, when using tuples.<\/p>\n<p>TypeScript 4.0 brings two fundamental changes, along with inference improvements, to make typing these possible.<\/p>\n<p>The first change is that spreads in tuple type syntax can now be generic. This means that we can represent higher-order operations on tuples and arrays even when we don\u2019t know the actual types we\u2019re operating over. When generic spreads are instantiated (or, replaced with a real type) in these tuple types, they can produce other sets of array and tuple types.<\/p>\n<p>For example, that means we can type function like <code>tail<\/code>, without our \u201cdeath by a thousand overloads\u201d issue.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>function<\/span> <span class=\"pl-en\">tail<\/span><span class=\"pl-c1\">&lt;<\/span><span>T<\/span> <span>extends<\/span> <span>any<\/span><span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr<\/span>: <span class=\"pl-smi\">readonly<\/span> <span class=\"pl-kos\">[<\/span><span>any<\/span><span class=\"pl-kos\">,<\/span> ...<span>T<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span> <span>const<\/span> <span class=\"pl-kos\">[<\/span><span class=\"pl-s1\">_ignored<\/span><span class=\"pl-kos\">,<\/span> ...<span class=\"pl-s1\">rest<\/span><span class=\"pl-kos\">]<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">arr<\/span><span class=\"pl-kos\">;<\/span> <span>return<\/span> <span class=\"pl-s1\">rest<\/span><span class=\"pl-kos\">;<\/span>\n<span class=\"pl-kos\">}<\/span> <span>const<\/span> <span class=\"pl-s1\">myTuple<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span><span>1<\/span><span class=\"pl-kos\">,<\/span> <span>2<\/span><span class=\"pl-kos\">,<\/span> <span>3<\/span><span class=\"pl-kos\">,<\/span> <span>4<\/span><span class=\"pl-kos\">]<\/span> <span>as<\/span> <span class=\"pl-smi\">const<\/span><span class=\"pl-kos\">;<\/span>\n<span>const<\/span> <span class=\"pl-s1\">myArray<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span><span>\"hello\"<\/span><span class=\"pl-kos\">,<\/span> <span>\"world\"<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span> <span>\/\/ type [2, 3, 4]<\/span>\n<span>const<\/span> <span class=\"pl-s1\">r1<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-en\">tail<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">myTuple<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span> <span>\/\/ type [2, 3, 4, ...string[]]<\/span>\n<span>const<\/span> <span class=\"pl-s1\">r2<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-en\">tail<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">[<\/span>...<span class=\"pl-s1\">myTuple<\/span><span class=\"pl-kos\">,<\/span> ...<span class=\"pl-s1\">myArray<\/span><span class=\"pl-kos\">]<\/span> <span>as<\/span> <span class=\"pl-smi\">const<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>The second change is that rest elements can occur anywhere in a tuple \u2013 not just at the end!<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>type<\/span> <span>Strings<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span><span>string<\/span><span class=\"pl-kos\">,<\/span> <span>string<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\n<span>type<\/span> <span>Numbers<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span><span>number<\/span><span class=\"pl-kos\">,<\/span> <span>number<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span> <span>\/\/ [string, string, number, number, boolean]<\/span>\n<span>type<\/span> <span>StrStrNumNumBool<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span>...<span>Strings<\/span><span class=\"pl-kos\">,<\/span> ...<span>Numbers<\/span><span class=\"pl-kos\">,<\/span> <span>boolean<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>Previously, TypeScript would issue an error like the following:<\/p>\n<pre><code>A rest element must be last in a tuple type.\n<\/code><\/pre>\n<p>But with TypeScript 4.0, this restriction is relaxed.<\/p>\n<p>Note that in cases when we spread in a type without a known length, the resulting type becomes unbounded as well, and all the following elements factor into the resulting rest element type.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>type<\/span> <span>Strings<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span><span>string<\/span><span class=\"pl-kos\">,<\/span> <span>string<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\n<span>type<\/span> <span>Numbers<\/span> <span class=\"pl-c1\">=<\/span> <span>number<\/span><span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span> <span>\/\/ [string, string, ...Array&lt;number | boolean&gt;]<\/span>\n<span>type<\/span> <span>Unbounded<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span>...<span>Strings<\/span><span class=\"pl-kos\">,<\/span> ...<span>Numbers<\/span><span class=\"pl-kos\">,<\/span> <span>boolean<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>By combining both of these behaviors together, we can write a single well-typed signature for <code>concat<\/code>:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>type<\/span> <span>Arr<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-smi\">readonly<\/span> any<span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span> <span>function<\/span> <span class=\"pl-en\">concat<\/span><span class=\"pl-c1\">&lt;<\/span><span>T<\/span> <span>extends<\/span> <span>Arr<\/span><span class=\"pl-kos\">,<\/span> <span>U<\/span> <span>extends<\/span> <span>Arr<\/span><span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span>T<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">arr2<\/span>: <span>U<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-kos\">[<\/span>...<span>T<\/span><span class=\"pl-kos\">,<\/span> ...<span>U<\/span><span class=\"pl-kos\">]<\/span> <span class=\"pl-kos\">{<\/span> <span>return<\/span> <span class=\"pl-kos\">[<\/span>...<span class=\"pl-s1\">arr1<\/span><span class=\"pl-kos\">,<\/span> ...<span class=\"pl-s1\">arr2<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>While that one signature is still a bit lengthy, it\u2019s just one signature that doesn\u2019t have to be repeated, and it gives predictable behavior on all arrays and tuples.<\/p>\n<p>This functionality on its own is great, but it shines in more sophisticated scenarios too. For example, consider a function to <a href=\"https:\/\/en.wikipedia.org\/wiki\/Partial_application\" rel=\"nofollow\">partially apply arguments<\/a> called <code>partialCall<\/code>. <code>partialCall<\/code> takes a function \u2013 let\u2019s call it <code>f<\/code> \u2013 along with the initial few arguments that <code>f<\/code> expects. It then returns a new function that takes any other arguments that <code>f<\/code> still needs, and calls <code>f<\/code> when it receives them.<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\"><span>function<\/span> <span class=\"pl-en\">partialCall<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">f<\/span><span class=\"pl-kos\">,<\/span> ...<span class=\"pl-s1\">headArgs<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span> <span>return<\/span> <span class=\"pl-kos\">(<\/span>...<span class=\"pl-s1\">tailArgs<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-c1\">=&gt;<\/span> <span class=\"pl-s1\">f<\/span><span class=\"pl-kos\">(<\/span>...<span class=\"pl-s1\">headArgs<\/span><span class=\"pl-kos\">,<\/span> ...<span class=\"pl-s1\">tailArgs<\/span><span class=\"pl-kos\">)<\/span>\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>TypeScript 4.0 improves the inference process for rest parameters and rest tuple elements so that we can type this and have it \u201cjust work\u201d.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>type<\/span> <span>Arr<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-smi\">readonly<\/span> <span class=\"pl-s1\">unknown<\/span><span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span> <span>function<\/span> <span class=\"pl-en\">partialCall<\/span><span class=\"pl-c1\">&lt;<\/span><span>T<\/span> <span>extends<\/span> <span>Arr<\/span><span class=\"pl-kos\">,<\/span> <span>U<\/span> <span>extends<\/span> <span>Arr<\/span><span class=\"pl-kos\">,<\/span> <span>R<\/span><span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span> <span class=\"pl-s1\">f<\/span>: <span class=\"pl-kos\">(<\/span>...<span class=\"pl-s1\">args<\/span>: <span class=\"pl-kos\">[<\/span>...<span>T<\/span><span class=\"pl-kos\">,<\/span> ...<span>U<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-c1\">=&gt;<\/span> <span>R<\/span><span class=\"pl-kos\">,<\/span> ...<span class=\"pl-s1\">headArgs<\/span>: <span>T<\/span>\n<span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span> <span>return<\/span> <span class=\"pl-kos\">(<\/span>...<span class=\"pl-s1\">tailArgs<\/span>: <span>U<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-c1\">=&gt;<\/span> <span class=\"pl-en\">f<\/span><span class=\"pl-kos\">(<\/span>...<span class=\"pl-s1\">headArgs<\/span><span class=\"pl-kos\">,<\/span> ...<span class=\"pl-s1\">tailArgs<\/span><span class=\"pl-kos\">)<\/span>\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>In this case, <code>partialCall<\/code> understands which parameters it can and can\u2019t initially take, and returns functions that appropriately accept and reject anything left over.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>const<\/span> <span class=\"pl-en\">foo<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">x<\/span>: <span>string<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">y<\/span>: <span>number<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">z<\/span>: <span>boolean<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-c1\">=&gt;<\/span> <span class=\"pl-kos\">{<\/span><span class=\"pl-kos\">}<\/span> <span>\/\/ This doesn't work because we're feeding in the wrong type for 'x'.<\/span>\n<span>const<\/span> <span class=\"pl-s1\">f1<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-en\">partialCall<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">foo<\/span><span class=\"pl-kos\">,<\/span> <span>100<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\n<span>\/\/ ~~~<\/span>\n<span>\/\/ error! Argument of type 'number' is not assignable to parameter of type 'string'.<\/span> <span>\/\/ This doesn't work because we're passing in too many arguments.<\/span>\n<span>const<\/span> <span class=\"pl-s1\">f2<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-en\">partialCall<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">foo<\/span><span class=\"pl-kos\">,<\/span> <span>\"hello\"<\/span><span class=\"pl-kos\">,<\/span> <span>100<\/span><span class=\"pl-kos\">,<\/span> <span>true<\/span><span class=\"pl-kos\">,<\/span> <span>\"oops\"<\/span><span class=\"pl-kos\">)<\/span>\n<span>\/\/ ~~~~~~<\/span>\n<span>\/\/ error! Expected 4 arguments, but got 5.<\/span> <span>\/\/ This works! It has the type '(y: number, z: boolean) =&gt; void'<\/span>\n<span>const<\/span> <span class=\"pl-s1\">f3<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-en\">partialCall<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">foo<\/span><span class=\"pl-kos\">,<\/span> <span>\"hello\"<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span> <span>\/\/ What can we do with f3 now?<\/span> <span class=\"pl-en\">f3<\/span><span class=\"pl-kos\">(<\/span><span>123<\/span><span class=\"pl-kos\">,<\/span> <span>true<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span> <span>\/\/ works!<\/span> <span class=\"pl-en\">f3<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\n<span>\/\/ error! Expected 2 arguments, but got 0.<\/span> <span class=\"pl-en\">f3<\/span><span class=\"pl-kos\">(<\/span><span>123<\/span><span class=\"pl-kos\">,<\/span> <span>\"hello\"<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\n<span>\/\/ ~~~~~~~<\/span>\n<span>\/\/ error! Argument of type 'string' is not assignable to parameter of type 'boolean'.<\/span><\/pre>\n<\/div>\n<p>Variadic tuple types enable a lot of new exciting patterns, especially around function composition. We expect we may be able to leverage it to do a better job type-checking JavaScript\u2019s built-in <code>bind<\/code> method. A handful of other inference improvements and patterns also went into this, and if you\u2019re interested in learning more, you can take a look at <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/39094\">the pull request<\/a> for variadic tuples.<\/p>\n<h2 id=\"labeled-tuple-elements\">Labeled Tuple Elements<\/h2>\n<p>Improving the experience around tuple types and parameter lists is important because it allows us to get strongly typed validation around common JavaScript idioms \u2013 really just slicing and dicing argument lists and passing them to other functions. The idea that we can use tuple types for rest parameters is one place where this is crucial.<\/p>\n<p>For example, the following function that uses a tuple type as a rest parameter\u2026<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>function<\/span> <span class=\"pl-en\">foo<\/span><span class=\"pl-kos\">(<\/span>...<span class=\"pl-s1\">args<\/span>: <span class=\"pl-kos\">[<\/span><span>string<\/span><span class=\"pl-kos\">,<\/span> <span>number<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-smi\"><span>void<\/span><\/span> <span class=\"pl-kos\">{<\/span> <span>\/\/ ...<\/span>\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>\u2026should appear no different from the following function\u2026<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>function<\/span> <span class=\"pl-en\">foo<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arg0<\/span>: <span>string<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">arg1<\/span>: <span>number<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-smi\"><span>void<\/span><\/span> <span class=\"pl-kos\">{<\/span> <span>\/\/ ...<\/span>\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>\u2026for any caller of <code>foo<\/code>.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span class=\"pl-en\">foo<\/span><span class=\"pl-kos\">(<\/span><span>\"hello\"<\/span><span class=\"pl-kos\">,<\/span> <span>42<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span> <span>\/\/ works<\/span> <span class=\"pl-en\">foo<\/span><span class=\"pl-kos\">(<\/span><span>\"hello\"<\/span><span class=\"pl-kos\">,<\/span> <span>42<\/span><span class=\"pl-kos\">,<\/span> <span>true<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span> <span>\/\/ error<\/span>\n<span class=\"pl-en\">foo<\/span><span class=\"pl-kos\">(<\/span><span>\"hello\"<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span> <span>\/\/ error<\/span><\/pre>\n<\/div>\n<p>There is one place where the differences begin to become observable though: readability. In the first example, we have no parameter names for the first and second elements. While these have no impact on type-checking, the lack of labels on tuple positions can make them harder to use \u2013 harder to communicate our intent.<\/p>\n<p>That\u2019s why in TypeScript 4.0, tuples types can now provide labels.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>type<\/span> <span>Range<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span><span class=\"pl-smi\">start<\/span>: number<span class=\"pl-kos\">,<\/span> <span class=\"pl-smi\">end<\/span>: number<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>To deepen the connection between parameter lists and tuple types, the syntax for rest elements and optional elements mirrors the syntax for parameter lists.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>type<\/span> <span>Foo<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span><span class=\"pl-smi\">first<\/span>: number<span class=\"pl-kos\">,<\/span> <span class=\"pl-smi\">second<\/span>?: string<span class=\"pl-kos\">,<\/span> ...<span class=\"pl-smi\">rest<\/span>: any<span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>There are a few rules when using labeled tuples. For one, when labeling a tuple element, all other elements in the tuple must also be labeled.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>type<\/span> <span>Bar<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span><span class=\"pl-smi\">first<\/span>: string<span class=\"pl-kos\">,<\/span> <span>number<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\n<span>\/\/ ~~~~~~<\/span>\n<span>\/\/ error! Tuple members must all have names or all not have names.<\/span><\/pre>\n<\/div>\n<p>It\u2019s worth noting \u2013 labels don\u2019t require us to name our variables differently when destructuring. They\u2019re purely there for documentation and tooling.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>function<\/span> <span class=\"pl-en\">foo<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">x<\/span>: <span class=\"pl-kos\">[<\/span><span class=\"pl-s1\">first<\/span>: <span>string<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">second<\/span>: <span>number<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span> <span>\/\/ ...<\/span> <span>\/\/ note: we didn't need to name these 'first' and 'second'<\/span> <span>let<\/span> <span class=\"pl-kos\">[<\/span><span class=\"pl-s1\">a<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">b<\/span><span class=\"pl-kos\">]<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">x<\/span><span class=\"pl-kos\">;<\/span> <span>\/\/ ...<\/span>\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>Overall, labeled tuples are handy when taking advantage of patterns around tuples and argument lists, along with implementing overloads in a type-safe way. In fact, TypeScript\u2019s editor support will try to display them as overloads when possible.<\/p>\n<p><img alt=\"Signature help displaying a union of labeled tuples as in a parameter list as two signatures\" data-gifffer=\"https:\/\/devblogs.microsoft.com\/typescript\/wp-content\/uploads\/sites\/11\/2020\/08\/signatureHelpLabeledTuples.gif\"><\/p>\n<p>To learn more, check out <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/38234\">the pull request<\/a> for labeled tuple elements.<\/p>\n<h2 id=\"class-property-inference\">Class Property Inference from Constructors<\/h2>\n<p>TypeScript 4.0 can now use control flow analysis to determine the types of properties in classes when <code>noImplicitAny<\/code> is enabled.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>class<\/span> <span>Square<\/span> <span class=\"pl-kos\">{<\/span> <span>\/\/ Previously: implicit any!<\/span> <span>\/\/ Now: inferred to `number`!<\/span> <span class=\"pl-c1\">area<\/span><span class=\"pl-kos\">;<\/span> <span class=\"pl-c1\">sideLength<\/span><span class=\"pl-kos\">;<\/span> <span class=\"pl-en\">constructor<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">sideLength<\/span>: <span>number<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span> <span>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> <span>this<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">area<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">sideLength<\/span> ** <span>2<\/span><span class=\"pl-kos\">;<\/span> <span class=\"pl-kos\">}<\/span>\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>In cases where not all paths of a constructor assign to an instance member, the property is considered to potentially be <code>undefined<\/code>.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>class<\/span> <span>Square<\/span> <span class=\"pl-kos\">{<\/span> <span class=\"pl-c1\">sideLength<\/span><span class=\"pl-kos\">;<\/span> <span class=\"pl-en\">constructor<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">sideLength<\/span>: <span>number<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span> <span>if<\/span> <span class=\"pl-kos\">(<\/span><span>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-kos\">)<\/span> <span class=\"pl-kos\">{<\/span> <span>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> <span class=\"pl-kos\">}<\/span> <span class=\"pl-kos\">}<\/span> <span>get<\/span> <span class=\"pl-en\">area<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span> <span>return<\/span> <span>this<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">sideLength<\/span> ** <span>2<\/span><span class=\"pl-kos\">;<\/span> <span>\/\/ ~~~~~~~~~~~~~~~<\/span> <span>\/\/ error! Object is possibly 'undefined'.<\/span> <span class=\"pl-kos\">}<\/span>\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>In cases where you know better (e.g. you have an <code>initialize<\/code> method of some sort), you\u2019ll still need an explicit type annotation along with a definite assignment assertion (<code>!<\/code>) if you\u2019re in <code>strictPropertyInitialization<\/code>.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>class<\/span> <span>Square<\/span> <span class=\"pl-kos\">{<\/span> <span>\/\/ definite assignment assertion<\/span> <span>\/\/ v<\/span> <span class=\"pl-c1\">sideLength<\/span>!: <span>number<\/span><span class=\"pl-kos\">;<\/span> <span>\/\/ ^^^^^^^^<\/span> <span>\/\/ type annotation<\/span> <span class=\"pl-en\">constructor<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">sideLength<\/span>: <span>number<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span> <span>this<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">initialize<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">sideLength<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">}<\/span> <span class=\"pl-en\">initialize<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">sideLength<\/span>: <span>number<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span> <span>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> <span class=\"pl-kos\">}<\/span> <span>get<\/span> <span class=\"pl-en\">area<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span> <span>return<\/span> <span>this<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">sideLength<\/span> ** <span>2<\/span><span class=\"pl-kos\">;<\/span> <span class=\"pl-kos\">}<\/span>\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>For more details, <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/379200\">see the implementing pull request<\/a>.<\/p>\n<h2 id=\"short-circuiting-assignment-operators\">Short-Circuiting Assignment Operators<\/h2>\n<p>JavaScript, and a lot of other languages, support a set of operators called <em>compound assignment<\/em> operators. Compound assignment operators apply an operator to two arguments, and then assign the result to the left side. You may have seen these before:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>\/\/ Addition<\/span>\n<span>\/\/ a = a + b<\/span>\n<span class=\"pl-s1\">a<\/span> <span class=\"pl-c1\">+=<\/span> <span class=\"pl-s1\">b<\/span><span class=\"pl-kos\">;<\/span> <span>\/\/ Subtraction<\/span>\n<span>\/\/ a = a - b<\/span>\n<span class=\"pl-s1\">a<\/span> <span class=\"pl-c1\">-=<\/span> <span class=\"pl-s1\">b<\/span><span class=\"pl-kos\">;<\/span> <span>\/\/ Multiplication<\/span>\n<span>\/\/ a = a * b<\/span>\n<span class=\"pl-s1\">a<\/span> *= <span class=\"pl-s1\">b<\/span><span class=\"pl-kos\">;<\/span> <span>\/\/ Division<\/span>\n<span>\/\/ a = a \/ b<\/span>\n<span class=\"pl-s1\">a<\/span> \/= <span class=\"pl-s1\">b<\/span><span class=\"pl-kos\">;<\/span> <span>\/\/ Exponentiation<\/span>\n<span>\/\/ a = a ** b<\/span>\n<span class=\"pl-s1\">a<\/span> **= <span class=\"pl-s1\">b<\/span><span class=\"pl-kos\">;<\/span> <span>\/\/ Left Bit Shift<\/span>\n<span>\/\/ a = a &lt;&lt; b<\/span>\n<span class=\"pl-s1\">a<\/span> &lt;&lt;= <span class=\"pl-s1\">b<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>So many operators in JavaScript have a corresponding assignment operator! Up until recently, however, there were three notable exceptions: logical <em>and<\/em> (<code>&amp;&amp;<\/code>), logical <em>or<\/em> (<code>||<\/code>), and nullish coalescing (<code>??<\/code>).<\/p>\n<p>That\u2019s why TypeScript 4.0 supports a new ECMAScript feature to add three new assignment operators: <code>&amp;&amp;=<\/code>, <code>||=<\/code>, and <code>??=<\/code>.<\/p>\n<p>These operators are great for substituting any example where a user might write code like the following:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span class=\"pl-s1\">a<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">a<\/span> <span class=\"pl-c1\">&amp;&amp;<\/span> <span class=\"pl-s1\">b<\/span><span class=\"pl-kos\">;<\/span>\n<span class=\"pl-s1\">a<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">a<\/span> <span class=\"pl-c1\">||<\/span> <span class=\"pl-s1\">b<\/span><span class=\"pl-kos\">;<\/span>\n<span class=\"pl-s1\">a<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">a<\/span> ?? <span class=\"pl-s1\">b<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>Or a similar <code>if<\/code> block like<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>\/\/ could be 'a ||= b'<\/span>\n<span>if<\/span> <span class=\"pl-kos\">(<\/span>!<span class=\"pl-s1\">a<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span> <span class=\"pl-s1\">a<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">b<\/span><span class=\"pl-kos\">;<\/span>\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>There are even some patterns we\u2019ve seen (or, uh, written ourselves) to lazily initialize values, only if they\u2019ll be needed.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>let<\/span> <span class=\"pl-s1\">values<\/span>: <span>string<\/span><span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span> <span>\/\/ Before<\/span>\n<span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">values<\/span> ?? <span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">values<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">push<\/span><span class=\"pl-kos\">(<\/span><span>\"hello\"<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span> <span>\/\/ After<\/span>\n<span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">values<\/span> ??<span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">push<\/span><span class=\"pl-kos\">(<\/span><span>\"hello\"<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>(look, we\u2019re not proud of <em>all<\/em> the code we write\u2026)<\/p>\n<p>On the rare case that you use getters or setters with side-effects, it\u2019s worth noting that these operators only perform assignments if necessary. In that sense, not only is the right side of the operator \u201cshort-circuited\u201d \u2013 the assignment itself is too.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span class=\"pl-s1\">obj<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">prop<\/span> <span class=\"pl-c1\">||<\/span><span class=\"pl-c1\">=<\/span> <span class=\"pl-en\">foo<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span> <span>\/\/ roughly equivalent to either of the following<\/span> <span class=\"pl-s1\">obj<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">prop<\/span> <span class=\"pl-c1\">||<\/span> <span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">obj<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">prop<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-en\">foo<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span> <span>if<\/span> <span class=\"pl-kos\">(<\/span>!<span class=\"pl-s1\">obj<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">prop<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span> <span class=\"pl-s1\">obj<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">prop<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-en\">foo<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p><a href=\"https:\/\/www.typescriptlang.org\/play?ts=Nightly#code\/MYewdgzgLgBCBGArGBeGBvAsAKBnmA5gKawAOATiKQBQCUGO+TMokIANkQHTsgHUAiYlChFyMABYBDCDHIBXMANoBuHI2Z4A9FpgAlIqXZTgRGAFsiAQg2byJeeTAwAslKgSu5KWAAmIczoYAB4YAAYuAFY1XHwAXwAaWxgIEhgKKmoAfQA3KXYALhh4EA4iH3osWM1WCDKePkFUkTFJGTlFZRimOJw4mJwAM0VgKABLcBhB0qCqplr63n4BcjGCCVgIMd8zIjz2eXciXy7k+yhHZygFIhje7BwFzgblgBUJMdlwM3yAdykAJ6yBSQGAeMzNUTkU7YBCILgZUioOBIBGUJEAHwxUxmqnU2Ce3CWgnenzgYDMACo6pZxpYIJSOqDwSkSFCYXC0VQYFi0NMQHQVEA\" rel=\"nofollow\">Try running the following example<\/a> to see how that differs from <em>always<\/em> performing the assignment.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>const<\/span> <span class=\"pl-s1\">obj<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">{<\/span> <span>get<\/span> <span class=\"pl-en\">prop<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span> <span class=\"pl-smi\">console<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">log<\/span><span class=\"pl-kos\">(<\/span><span>\"getter has run\"<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span> <span>\/\/ Replace me!<\/span> <span>return<\/span> <span>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>0.5<\/span><span class=\"pl-kos\">;<\/span> <span class=\"pl-kos\">}<\/span><span class=\"pl-kos\">,<\/span> <span>set<\/span> <span class=\"pl-en\">prop<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">_val<\/span>: <span>boolean<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span> <span class=\"pl-smi\">console<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">log<\/span><span class=\"pl-kos\">(<\/span><span>\"setter has run\"<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span> <span class=\"pl-kos\">}<\/span>\n<span class=\"pl-kos\">}<\/span><span class=\"pl-kos\">;<\/span> <span>function<\/span> <span class=\"pl-en\">foo<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span> <span class=\"pl-smi\">console<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">log<\/span><span class=\"pl-kos\">(<\/span><span>\"right side evaluated\"<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span> <span>return<\/span> <span>true<\/span><span class=\"pl-kos\">;<\/span>\n<span class=\"pl-kos\">}<\/span> <span class=\"pl-smi\">console<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">log<\/span><span class=\"pl-kos\">(<\/span><span>\"This one always runs the setter\"<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\n<span class=\"pl-s1\">obj<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">prop<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">obj<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">prop<\/span> <span class=\"pl-c1\">||<\/span> <span class=\"pl-en\">foo<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span> <span class=\"pl-smi\">console<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">log<\/span><span class=\"pl-kos\">(<\/span><span>\"This one *sometimes* runs the setter\"<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\n<span class=\"pl-s1\">obj<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">prop<\/span> <span class=\"pl-c1\">||<\/span><span class=\"pl-c1\">=<\/span> <span class=\"pl-en\">foo<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>We\u2019d like to extend a big thanks to community member <a href=\"https:\/\/github.com\/Kingwl\">Wenlu Wang<\/a> for this contribution!<\/p>\n<p>For more details, you can <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/37727\">take a look at the pull request here<\/a>. You can also <a href=\"https:\/\/github.com\/tc39\/proposal-logical-assignment\/\">check out TC39\u2019s proposal repository for this feature<\/a>.<\/p>\n<h2 id=\"unknown-on-catch\"><code>unknown<\/code> on <code>catch<\/code> Clause Bindings<\/h2>\n<p>Since the beginning days of TypeScript, <code>catch<\/code> clause variables have always been typed as <code>any<\/code>. This meant that TypeScript allowed you to do anything you wanted with them.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>try<\/span> <span class=\"pl-kos\">{<\/span> <span>\/\/ ...<\/span>\n<span class=\"pl-kos\">}<\/span>\n<span>catch<\/span> <span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">x<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span> <span>\/\/ x has type 'any' - have fun!<\/span> <span class=\"pl-smi\">console<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">log<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">x<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">message<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span> <span class=\"pl-smi\">console<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">log<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">x<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">toUpperCase<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span> <span class=\"pl-s1\">x<\/span><span class=\"pl-c1\">++<\/span><span class=\"pl-kos\">;<\/span> <span class=\"pl-s1\">x<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">yadda<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">yadda<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">yadda<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>The above has some undesirable behavior if we\u2019re trying to prevent <em>more<\/em> errors from happening in our error-handling code! Because these variables have the type <code>any<\/code> by default, they lack any type-safety which could have errored on invalid operations.<\/p>\n<p>That\u2019s why TypeScript 4.0 now lets you specify the type of <code>catch<\/code> clause variables as <code>unknown<\/code> instead. <code>unknown<\/code> is safer than <code>any<\/code> because it reminds us that we need to perform some sorts of type-checks before operating on our values.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>try<\/span> <span class=\"pl-kos\">{<\/span> <span>\/\/ ...<\/span>\n<span class=\"pl-kos\">}<\/span>\n<span>catch<\/span> <span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">e<\/span>: <span class=\"pl-s1\">unknown<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span> <span>\/\/ error!<\/span> <span>\/\/ Property 'toUpperCase' does not exist on type 'unknown'.<\/span> <span class=\"pl-smi\">console<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">log<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">e<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">toUpperCase<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span> <span>if<\/span> <span class=\"pl-kos\">(<\/span><span>typeof<\/span> <span class=\"pl-s1\">e<\/span> <span class=\"pl-c1\">===<\/span> <span>\"string\"<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span> <span>\/\/ works!<\/span> <span>\/\/ We've narrowed 'e' down to the type 'string'.<\/span> <span class=\"pl-smi\">console<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">log<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">e<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">toUpperCase<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span> <span class=\"pl-kos\">}<\/span>\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>While the types of <code>catch<\/code> variables won\u2019t change by default, we might consider a new <code>--strict<\/code> mode flag in the future so that users can opt in to this behavior. In the meantime, it should be possible to write a lint rule to force <code>catch<\/code> variables to have an explicit annotation of either <code>: any<\/code> or <code>: unknown<\/code>.<\/p>\n<p>For more details you can <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/39015\">peek at the changes for this feature<\/a>.<\/p>\n<h2 id=\"custom-jsx-factories\">Custom JSX Factories<\/h2>\n<p>When using JSX, a <a href=\"https:\/\/reactjs.org\/docs\/fragments.html\" rel=\"nofollow\"><em>fragment<\/em><\/a> is a type of JSX element that allows us to return multiple child elements. When we first implemented fragments in TypeScript, we didn\u2019t have a great idea about how other libraries would utilize them. Nowadays most other libraries that encourage using JSX and support fragments have a similar API shape.<\/p>\n<p>In TypeScript 4.0, users can customize the fragment factory through the new <code>jsxFragmentFactory<\/code> option.<\/p>\n<p>As an example, the following <code>tsconfig.json<\/code> file tells TypeScript to transform JSX in a way compatible with React, but switches each factory invocation to <code>h<\/code> instead of <code>React.createElement<\/code>, and uses <code>Fragment<\/code> instead of <code>React.Fragment<\/code>.<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\"><span class=\"pl-kos\">{<\/span> <span>\"compilerOptions\"<\/span>: <span class=\"pl-kos\">{<\/span> <span>\"target\"<\/span>: <span>\"esnext\"<\/span><span class=\"pl-kos\">,<\/span> <span>\"module\"<\/span>: <span>\"commonjs\"<\/span><span class=\"pl-kos\">,<\/span> <span>\"jsx\"<\/span>: <span>\"react\"<\/span><span class=\"pl-kos\">,<\/span> <span>\"jsxFactory\"<\/span>: <span>\"h\"<\/span><span class=\"pl-kos\">,<\/span> <span>\"jsxFragmentFactory\"<\/span>: <span>\"Fragment\"<\/span> <span class=\"pl-kos\">}<\/span>\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>In cases where you need to have a different JSX factory on a per-file basis, you can take advantage of the new <code>\/** @jsxFrag *\/<\/code> pragma comment. For example, the following\u2026<\/p>\n<div class=\"highlight highlight-source-tsx\">\n<pre class=\"lang:default decode:true\"><span>\/\/ Note: these pragma comments need to be written<\/span>\n<span>\/\/ with a JSDoc-style multiline syntax to take effect.<\/span>\n<span>\/** <span class=\"pl-k\">@jsx<\/span> h *\/<\/span>\n<span>\/** <span class=\"pl-k\">@jsxFrag<\/span> Fragment *\/<\/span> <span>import<\/span> <span class=\"pl-kos\">{<\/span> <span class=\"pl-s1\">h<\/span><span class=\"pl-kos\">,<\/span> <span>Fragment<\/span> <span class=\"pl-kos\">}<\/span> <span>from<\/span> <span>\"preact\"<\/span><span class=\"pl-kos\">;<\/span> <span>let<\/span> <span class=\"pl-s1\">stuff<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-c1\">&lt;<\/span><span class=\"pl-c1\">&gt;<\/span> <span class=\"pl-c1\">&lt;<\/span><span class=\"pl-ent\">div<\/span><span class=\"pl-c1\">&gt;<\/span>Hello<span class=\"pl-c1\">&lt;<\/span>\/<span class=\"pl-ent\">div<\/span><span class=\"pl-c1\">&gt;<\/span>\n<span class=\"pl-c1\">&lt;<\/span>\/<span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>\u2026will get transformed to this output JavaScript\u2026<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\"><span>\/\/ Note: these pragma comments need to be written<\/span>\n<span>\/\/ with a JSDoc-style multiline syntax to take effect.<\/span>\n<span>\/** <span class=\"pl-k\">@jsx<\/span> h *\/<\/span>\n<span>\/** <span class=\"pl-k\">@jsxFrag<\/span> Fragment *\/<\/span>\n<span>import<\/span> <span class=\"pl-kos\">{<\/span> <span class=\"pl-s1\">h<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-v\">Fragment<\/span> <span class=\"pl-kos\">}<\/span> <span>from<\/span> <span>\"preact\"<\/span><span class=\"pl-kos\">;<\/span>\n<span>let<\/span> <span class=\"pl-s1\">stuff<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-en\">h<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-v\">Fragment<\/span><span class=\"pl-kos\">,<\/span> <span>null<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-en\">h<\/span><span class=\"pl-kos\">(<\/span><span>\"div\"<\/span><span class=\"pl-kos\">,<\/span> <span>null<\/span><span class=\"pl-kos\">,<\/span> <span>\"Hello\"<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>We\u2019d like to extend a big thanks to community member <a href=\"https:\/\/github.com\/nojvek\">Noj Vek<\/a> for sending this pull request and patiently working with our team on it.<\/p>\n<p>You can see that <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/38720\">the pull request<\/a> for more details!<\/p>\n<h2 id=\"build-and-noemitonerror\">Speed Improvements in <code>build<\/code> mode with <code>--noEmitOnError<\/code><\/h2>\n<p>Previously, compiling a program after a previous compile with errors under <code>--incremental<\/code> would be extremely slow when using the <code>--noEmitOnError<\/code> flag. This is because none of the information from the last compilation would be cached in a <code>.tsbuildinfo<\/code> file based on the <code>--noEmitOnError<\/code> flag.<\/p>\n<p>TypeScript 4.0 changes this which gives a great speed boost in these scenarios, and in turn improves <code>--build<\/code> mode scenarios (which imply both <code>--incremental<\/code> and <code>--noEmitOnError<\/code>).<\/p>\n<p>For details, <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/38853\">read up more on the pull request<\/a>.<\/p>\n<h2 id=\"noemit-and-incremental\"><code>--incremental<\/code> with <code>--noEmit<\/code><\/h2>\n<p>TypeScript 4.0 allows us to use the <code>--noEmit<\/code> flag when while still leveraging <code>--incremental<\/code> compiles. This was previously not allowed, as <code>--incremental<\/code> needs to emit a <code>.tsbuildinfo<\/code> files; however, the use-case to enable faster incremental builds is important enough to enable for all users.<\/p>\n<p>For more details, you can <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/39122\">see the implementing pull request<\/a>.<\/p>\n<h2 id=\"editor-improvements\">Editor Improvements<\/h2>\n<p>The TypeScript compiler doesn\u2019t only power the editing experience for TypeScript itself in most major editors \u2013 it also powers the JavaScript experience in the Visual Studio family of editors and more. For that reason, much of our work focuses on improving editor scenarios \u2013 the place you spend most of your time as a developer.<\/p>\n<p>Using new TypeScript\/JavaScript functionality in your editor will differ depending on your editor, but<\/p>\n<p>You can check out a partial <a href=\"https:\/\/github.com\/Microsoft\/TypeScript\/wiki\/TypeScript-Editor-Support\">list of editors that have support for TypeScript<\/a> to learn more about whether your favorite editor has support to use new versions.<\/p>\n<h3 id=\"convert-to-optional-chaining\">Convert to Optional Chaining<\/h3>\n<p>Optional chaining is a recent feature that\u2019s received a lot of love. That\u2019s why TypeScript 4.0 brings a new refactoring to convert common patterns to take advantage of <a href=\"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-3-7\/#optional-chaining\" rel=\"nofollow\">optional chaining<\/a> and <a href=\"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-3-7\/#nullish-coalescing\" rel=\"nofollow\">nullish coalescing<\/a>!<\/p>\n<p><img alt=\"Converting a &amp;&amp; a.b.c &amp;&amp; a.b.c.d.e.f() to a?.b.c?.d.e.f.()\" data-gifffer=\"https:\/\/devblogs.microsoft.com\/typescript\/wp-content\/uploads\/sites\/11\/2020\/08\/convertToOptionalChain-4-0.gif\"><\/p>\n<p>Keep in mind that while this refactoring doesn\u2019t <em>perfectly<\/em> capture the same behavior due to subtleties with truthiness\/falsiness in JavaScript, we believe it should capture the intent for most use-cases, especially when TypeScript has more precise knowledge of your types.<\/p>\n<p>For more details, <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/39135\">check out the pull request for this feature<\/a>.<\/p>\n<h3 id=\"deprecated-support\"><code>\/** @deprecated *\/<\/code> Support<\/h3>\n<p>TypeScript\u2019s editing support now recognizes when a declaration has been marked with a <code>\/** @deprecated *<\/code> JSDoc comment. That information is surfaced in completion lists and as a suggestion diagnostic that editors can handle specially. In an editor like VS Code, deprecated values are typically displayed a strike-though style <del>like this<\/del>.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2020\/08\/developers-learn-whats-new-in-typescript-4-0.png\" alt=\"Some examples of deprecated declarations with strikethrough text in the editor\"><\/p>\n<p>This new functionality is available thanks to <a href=\"https:\/\/github.com\/Kingwl\">Wenlu Wang<\/a>. See <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/38523\">the pull request<\/a> for more details.<\/p>\n<h3 id=\"partial-editing-mode\">Partial Semantic Mode at Startup<\/h3>\n<p>We\u2019ve heard a lot from users suffering from long startup times, especially on bigger projects. The culprit is usually a process called <em>program construction<\/em>. This is the process of starting with an initial set of root files, parsing them, finding their dependencies, parsing those dependencies, finding those dependencies\u2019 dependencies, and so on. The bigger your project is, the longer you\u2019ll have to wait before you can get basic editor operations like go-to-definition or quick info.<\/p>\n<p>That\u2019s why we\u2019ve been working on a new mode for editors to provide a <em>partial<\/em> experience until the full language service experience has loaded up. The core idea is that editors can run a lightweight partial server that only looks at the current files that the editor has open.<\/p>\n<p>It\u2019s hard to say precisely what sorts of improvements you\u2019ll see, but anecdotally, it used to take anywhere between <em>20 seconds to a minute<\/em> before TypeScript would become fully responsive on the Visual Studio Code codebase. In contrast, <strong>our new partial semantic mode seems to bring that delay down to just a few seconds<\/strong>. As an example, in the following video, you can see two side-by-side editors with TypeScript 3.9 running on the left and TypeScript 4.0 running on the right.<\/p>\n<p>When restarting both editors on a particularly large codebase, the one with TypeScript 3.9 can\u2019t provide completions or quick info at all. On the other hand, the editor with TypeScript 4.0 can <em>immediately<\/em> give us a rich experience in the current file we\u2019re editing, despite loading the full project in the background.<\/p>\n<p>Currently the only editor that supports this mode is <a href=\"http:\/\/code.visualstudio.com\/\" rel=\"nofollow\">Visual Studio Code<\/a> which has some UX improvements coming up in <a href=\"http:\/\/code.visualstudio.com\/insiders\" rel=\"nofollow\">Visual Studio Code Insiders<\/a>. We recognize that this experience may still have room for polish in UX and functionality, and we have <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/issues\/39035\">a list of improvements<\/a> in mind. We\u2019re looking for more feedback on what you think might be useful.<\/p>\n<p>For more information, you can <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/issues\/37713\">see the original proposal<\/a>, <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/38561\">the implementing pull request<\/a>, along with <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/issues\/39035\">the follow-up meta issue<\/a>.<\/p>\n<h3 id=\"smarter-auto-imports\">Smarter Auto-Imports<\/h3>\n<p>Auto-import is a fantastic feature that makes coding a lot easier; however, every time auto-import doesn\u2019t seem to work, it can throw users off a lot. One specific issue that we heard from users was that auto-imports didn\u2019t work on dependencies that were written in TypeScript \u2013 that is, until they wrote at least one explicit import somewhere else in their project.<\/p>\n<p>Why would auto-imports work for <code>@types<\/code> packages, but not for packages that ship their own types? It turns out that auto-imports only work on packages your project <em>already<\/em> includes. Because TypeScript has some quirky defaults that automatically add packages in <code>node_modules\/@types<\/code> to your project, <em>those<\/em> packages would be auto-imported. On the other hand, other packages were excluded because crawling through all your <code>node_modules<\/code> packages can be <em>really<\/em> expensive.<\/p>\n<p>All of this leads to a pretty lousy getting started experience for when you\u2019re trying to auto-import something that you\u2019ve just installed but haven\u2019t used yet.<\/p>\n<p>TypeScript 4.0 now does a little extra work in editor scenarios to include the packages you\u2019ve listed in your <code>package.json<\/code>\u2018s <code>dependencies<\/code> (and <code>peerDependencies<\/code>) fields. The information from these packages is only used to improve auto-imports, and doesn\u2019t change anything else like type-checking. This allows us to provide auto-imports for all of your dependencies that have types, without incurring the cost of a complete <code>node_modules<\/code> search.<\/p>\n<p>In the rare cases when your <code>package.json<\/code> lists more than ten typed dependencies that haven\u2019t been imported yet, this feature automatically disables itself to prevent slow project loading. To force the feature to work, or to disable it entirely, you should be able to configure your editor. For Visual Studio Code, this is the \u201cInclude Package JSON Auto Imports\u201d (or <code>typescript.preferences.includePackageJsonAutoImports<\/code>) setting.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2020\/08\/developers-learn-whats-new-in-typescript-4-0-1.png\" alt=\"Configuring 'include package JSON auto imports'\"> For more details, you can see the <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/issues\/37812\">proposal issue<\/a> along with <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/38923\">the implementing pull request<\/a>.<\/p>\n<h2 id=\"new-website\">Our New Website!<\/h2>\n<p><a href=\"https:\/\/www.typescriptlang.org\/\" rel=\"nofollow\">The TypeScript website<\/a> has recently been rewritten from the ground up and rolled out!<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2020\/08\/developers-learn-whats-new-in-typescript-4-0-2.png\" alt=\"A screenshot of the new TypeScript website\"><\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/typescript\/announcing-the-new-typescript-website\/\" rel=\"nofollow\">We already wrote a bit about our new site<\/a>, so you can read up more there; but it\u2019s worth mentioning that we\u2019re still looking to hear what you think! If you have questions, comments, or suggestions, you can <a href=\"https:\/\/github.com\/microsoft\/TypeScript-Website\">file them over on the website\u2019s issue tracker<\/a>.<\/p>\n<h2 id=\"breaking-changes\">Breaking Changes<\/h2>\n<h3 id=\"lib-d-ts-changes\"><code>lib.d.ts<\/code> Changes<\/h3>\n<p>Our <code>lib.d.ts<\/code> declarations have changed \u2013 most specifically, types for the DOM have changed. The most notable change may be the removal of <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Document\/origin\" rel=\"nofollow\"><code>document.origin<\/code><\/a> which only worked in old versions of IE and Safari MDN recommends moving to <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/WindowOrWorkerGlobalScope\/origin\" rel=\"nofollow\"><code>self.origin<\/code><\/a>.<\/p>\n<h3 id=\"properties-overriding-accessors-and-vice-versa-is-an-error\">Properties Overriding Accessors (and vice versa) is an Error<\/h3>\n<p>Previously, it was only an error for properties to override accessors, or accessors to override properties, when using <code>useDefineForClassFields<\/code>; however, TypeScript now always issues an error when declaring a property in a derived class that would override a getter or setter in the base class.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>class<\/span> <span>Base<\/span> <span class=\"pl-kos\">{<\/span> <span>get<\/span> <span class=\"pl-en\">foo<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span> <span>return<\/span> <span>100<\/span><span class=\"pl-kos\">;<\/span> <span class=\"pl-kos\">}<\/span> <span>set<\/span> <span class=\"pl-en\">foo<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span> <span>\/\/ ...<\/span> <span class=\"pl-kos\">}<\/span>\n<span class=\"pl-kos\">}<\/span> <span>class<\/span> <span>Derived<\/span> <span>extends<\/span> <span>Base<\/span> <span class=\"pl-kos\">{<\/span> <span class=\"pl-c1\">foo<\/span> <span class=\"pl-c1\">=<\/span> <span>10<\/span><span class=\"pl-kos\">;<\/span>\n<span>\/\/ ~~~<\/span>\n<span>\/\/ error!<\/span>\n<span>\/\/ 'foo' is defined as an accessor in class 'Base',<\/span>\n<span>\/\/ but is overridden here in 'Derived' as an instance property.<\/span>\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>class<\/span> <span>Base<\/span> <span class=\"pl-kos\">{<\/span> <span class=\"pl-c1\">prop<\/span> <span class=\"pl-c1\">=<\/span> <span>10<\/span><span class=\"pl-kos\">;<\/span>\n<span class=\"pl-kos\">}<\/span> <span>class<\/span> <span>Derived<\/span> <span>extends<\/span> <span>Base<\/span> <span class=\"pl-kos\">{<\/span> <span>get<\/span> <span class=\"pl-en\">prop<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span> <span>\/\/ ~~~~<\/span> <span>\/\/ error!<\/span> <span>\/\/ 'prop' is defined as a property in class 'Base', but is overridden here in 'Derived' as an accessor.<\/span> <span>return<\/span> <span>100<\/span><span class=\"pl-kos\">;<\/span> <span class=\"pl-kos\">}<\/span>\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>See more details on <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/37894\">the implementing pull request<\/a>.<\/p>\n<h3 id=\"operands-for-delete-must-be-optional\">Operands for <code>delete<\/code> must be optional.<\/h3>\n<p>When using the <code>delete<\/code> operator in <code>strictNullChecks<\/code>, the operand must now be <code>any<\/code>, <code>unknown<\/code>, <code>never<\/code>, or be optional (in that it contains <code>undefined<\/code> in the type). Otherwise, use of the <code>delete<\/code> operator is an error.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\"><span>interface<\/span> <span>Thing<\/span> <span class=\"pl-kos\">{<\/span> <span class=\"pl-c1\">prop<\/span>: <span>string<\/span><span class=\"pl-kos\">;<\/span>\n<span class=\"pl-kos\">}<\/span> <span>function<\/span> <span class=\"pl-en\">f<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">x<\/span>: <span>Thing<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span> <span>delete<\/span> <span class=\"pl-s1\">x<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">prop<\/span><span class=\"pl-kos\">;<\/span> <span>\/\/ ~~~~~~<\/span> <span>\/\/ error! The operand of a 'delete' operator must be optional.<\/span>\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>See more details on <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/37921\">the implementing pull request<\/a>.<\/p>\n<h3 id=\"usage-of-typescripts-node-factory-is-deprecated\">Usage of TypeScript\u2019s Node Factory is Deprecated<\/h3>\n<p>Today TypeScript provides a set of \u201cfactory\u201d functions for producing AST Nodes; however, TypeScript 4.0 provides a new node factory API. As a result, for TypeScript 4.0 we\u2019ve made the decision to deprecate these older functions in favor of the new ones.<\/p>\n<p>For more details, <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/35282\">read up on the relevant pull request for this change<\/a>.<\/p>\n<h2 id=\"whats-next\">What\u2019s Next?<\/h2>\n<p>You\u2019ve reached the end of this release post, but luckily there\u2019s more coming. <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/issues\/40124\">TypeScript 4.1\u2019s iteration plan<\/a> is already up so you can get a sense of what\u2019s on the horizon. In the meantime, you can give new features in 4.1 a shot by using <a href=\"https:\/\/www.typescriptlang.org\/docs\/handbook\/nightly-builds.html\" rel=\"nofollow\">nightly builds in your workspace<\/a>, or <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=ms-vscode.vscode-typescript-next\" rel=\"nofollow\">maybe just in your editor<\/a>. Whether you\u2019re on TypeScript 4.0, or the next version, we\u2019re interested in hearing feedback! Feel free to leave a comment below, <a href=\"https:\/\/twitter.com\/typescript\" rel=\"nofollow\">reach out over Twitter<\/a>, or <a href=\"https:\/\/github.com\/Microsoft\/TypeScript\/issues\/new\/choose\">file an issue on GitHub<\/a>.<\/p>\n<p>We said it once, and we\u2019ll say it again: we owe so much to our community for all their work and dedication. In turn, we want to making coding in TypeScript and JavaScript the pure joy you deserve. This involves not just focusing on one thing, but a combination of improving the language and editing experience, keeping an eye on speed, iterating on our UX, smoothing the onboarding and learning experience as a whole, and more.<\/p>\n<p>Thank you so much, and enjoy 4.0!<\/p>\n<p>Happy Hacking!<\/p>\n<p>\u2013 Daniel Rosenwasser and the TypeScript Team<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Daniel August 20th, 2020 Today we are thrilled to announce the availability of TypeScript 4.0! This version of the language represents our next generation of TypeScript releases, as we dive deeper into expressivity, productivity, and scalability. If you\u2019re not familiar with TypeScript, it\u2019s a language that builds on top of JavaScript by adding syntax for [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":116977,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[49],"tags":[467,50],"class_list":["post-116976","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-microsoft-news","tag-developers","tag-recent-news"],"_links":{"self":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/116976","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/comments?post=116976"}],"version-history":[{"count":0,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/116976\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/media\/116977"}],"wp:attachment":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/media?parent=116976"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/categories?post=116976"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/tags?post=116976"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}