{"id":2633,"date":"2020-06-26T08:59:16","date_gmt":"2020-06-26T16:59:16","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/typescript\/?p=2633"},"modified":"2020-08-04T13:56:25","modified_gmt":"2020-08-04T21:56:25","slug":"announcing-typescript-4-0-beta","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-4-0-beta\/","title":{"rendered":"Announcing TypeScript 4.0 Beta"},"content":{"rendered":"<p>Today we&#8217;re excited to release the beta of the next major milestone in the TypeScript programming language: TypeScript 4.0.<\/p>\n<p>This beta takes us on our first step into TypeScript 4.0, and while it brings a new major version, don&#8217;t fret &#8211; there are no substantially larger breaking changes than usual. Our philosophy in evolving TypeScript has always been to provide an upgrade path that minimizes disruptive breaking changes while still giving ourselves some flexibility to flag suspicious code as errors when appropriate. For this reason, we&#8217;re continuing with a similar versioning model to that of past releases, so 4.0 is just the natural continuation from TypeScript 3.9.<\/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-40beta\" 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>Now let&#8217;s take a look at what&#8217;s in store for TypeScript 4.0!<\/p>\n<ul>\n<li><a href=\"#variadic-tuple-types\">Variadic Tuple Types<\/a><\/li>\n<li><a href=\"#labeled-tuple-elements\">Labeled Tuple Elements<\/a><\/li>\n<li><a href=\"#class-property-inference\">Class Property Inference from Constructors<\/a><\/li>\n<li><a href=\"#short-circuiting-assignment-operators\">Short-Circuiting Assignment Operators<\/a><\/li>\n<li><a href=\"#unknown-on-catch\"><code>unknown<\/code> on <code>catch<\/code> Clauses<\/a><\/li>\n<li><a href=\"#custom-jsx-factories\">Custom JSX Factories<\/a><\/li>\n<li><a href=\"#build-and-noemitonerror\">Speed Improvements in <code>build<\/code> mode with <code>--noEmitOnError<\/code><\/a><\/li>\n<li><a href=\"#noemit-and-incremental\"><code>--incremental<\/code> with <code>--noEmit<\/code><\/a><\/li>\n<li><a href=\"#editor-improvements\">Editor Improvements<\/a>\n<ul>\n<li><a href=\"#deprecated-support\"><code>\/** @deprecated *\/<\/code> Support<\/a><\/li>\n<li><a href=\"#partial-editing-mode\">Partial Editing Mode at Startup<\/a><\/li>\n<li><a href=\"#smarter-auto-imports\">Smarter Auto-Imports<\/a><\/li>\n<\/ul>\n<\/li>\n<li><a href=\"#breaking-changes\">Breaking Changes<\/a><\/li>\n<\/ul>\n<h2><a name=\"variadic-tuple-types\"><\/a> 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 as a new array.<\/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 style=\"color: #0000ff;\">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>\r\n    <span style=\"color: #0000ff;\">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>\r\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\" style=\"background-color: #f0f0f0; padding: 10px; border-radius: 10px;\"><span style=\"color: #0000ff;\">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>\r\n    <span style=\"color: #0000ff;\">const<\/span> <span class=\"pl-kos\">[<\/span><span class=\"pl-c1\">_<\/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>\r\n    <span style=\"color: #0000ff;\">return<\/span> <span class=\"pl-s1\">result<\/span>\r\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\" style=\"background-color: #f0f0f0; padding: 10px; border-radius: 10px;\"><span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/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 class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-kos\">[<\/span>A<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span>A<span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span class=\"pl-kos\">[<\/span>A<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>A<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span>A<span class=\"pl-kos\">,<\/span> B<span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span class=\"pl-kos\">[<\/span>A<span class=\"pl-kos\">,<\/span> B<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>A<span class=\"pl-kos\">,<\/span> B<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span>A<span class=\"pl-kos\">,<\/span> B<span class=\"pl-kos\">,<\/span> C<span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span class=\"pl-kos\">[<\/span>A<span class=\"pl-kos\">,<\/span> B<span class=\"pl-kos\">,<\/span> C<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>A<span class=\"pl-kos\">,<\/span> B<span class=\"pl-kos\">,<\/span> C<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span>A<span class=\"pl-kos\">,<\/span> B<span class=\"pl-kos\">,<\/span> C<span class=\"pl-kos\">,<\/span> D<span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span class=\"pl-kos\">[<\/span>A<span class=\"pl-kos\">,<\/span> B<span class=\"pl-kos\">,<\/span> C<span class=\"pl-kos\">,<\/span> D<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>A<span class=\"pl-kos\">,<\/span> B<span class=\"pl-kos\">,<\/span> C<span class=\"pl-kos\">,<\/span> D<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span>A<span class=\"pl-kos\">,<\/span> B<span class=\"pl-kos\">,<\/span> C<span class=\"pl-kos\">,<\/span> D<span class=\"pl-kos\">,<\/span> E<span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span class=\"pl-kos\">[<\/span>A<span class=\"pl-kos\">,<\/span> B<span class=\"pl-kos\">,<\/span> C<span class=\"pl-kos\">,<\/span> D<span class=\"pl-kos\">,<\/span> E<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>A<span class=\"pl-kos\">,<\/span> B<span class=\"pl-kos\">,<\/span> C<span class=\"pl-kos\">,<\/span> D<span class=\"pl-kos\">,<\/span> E<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span>A<span class=\"pl-kos\">,<\/span> B<span class=\"pl-kos\">,<\/span> C<span class=\"pl-kos\">,<\/span> D<span class=\"pl-kos\">,<\/span> E<span class=\"pl-kos\">,<\/span> F<span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span class=\"pl-kos\">[<\/span>A<span class=\"pl-kos\">,<\/span> B<span class=\"pl-kos\">,<\/span> C<span class=\"pl-kos\">,<\/span> D<span class=\"pl-kos\">,<\/span> E<span class=\"pl-kos\">,<\/span> F<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>A<span class=\"pl-kos\">,<\/span> B<span class=\"pl-kos\">,<\/span> C<span class=\"pl-kos\">,<\/span> D<span class=\"pl-kos\">,<\/span> E<span class=\"pl-kos\">,<\/span> F<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span><span class=\"pl-kos\">)<\/span><\/pre>\n<\/div>\n<p>Uh&#8230;okay, that&#8217;s&#8230;seven overloads for when the second array is always empty. Let&#8217;s 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\" style=\"background-color: #f0f0f0; padding: 10px; border-radius: 10px;\"><span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span>A2<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>A2<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-kos\">[<\/span>A2<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span>A1<span class=\"pl-kos\">,<\/span> A2<span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span class=\"pl-kos\">[<\/span>A1<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">arr2<\/span>: <span class=\"pl-kos\">[<\/span>A2<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-kos\">[<\/span>A1<span class=\"pl-kos\">,<\/span> A2<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span>A1<span class=\"pl-kos\">,<\/span> B1<span class=\"pl-kos\">,<\/span> A2<span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span class=\"pl-kos\">[<\/span>A1<span class=\"pl-kos\">,<\/span> B1<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">arr2<\/span>: <span class=\"pl-kos\">[<\/span>A2<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-kos\">[<\/span>A1<span class=\"pl-kos\">,<\/span> B1<span class=\"pl-kos\">,<\/span> A2<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span>A1<span class=\"pl-kos\">,<\/span> B1<span class=\"pl-kos\">,<\/span> C1<span class=\"pl-kos\">,<\/span> A2<span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span class=\"pl-kos\">[<\/span>A1<span class=\"pl-kos\">,<\/span> B1<span class=\"pl-kos\">,<\/span> C1<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">arr2<\/span>: <span class=\"pl-kos\">[<\/span>A2<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-kos\">[<\/span>A1<span class=\"pl-kos\">,<\/span> B1<span class=\"pl-kos\">,<\/span> C1<span class=\"pl-kos\">,<\/span> A2<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span>A1<span class=\"pl-kos\">,<\/span> B1<span class=\"pl-kos\">,<\/span> C1<span class=\"pl-kos\">,<\/span> D1<span class=\"pl-kos\">,<\/span> A2<span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span class=\"pl-kos\">[<\/span>A1<span class=\"pl-kos\">,<\/span> B1<span class=\"pl-kos\">,<\/span> C1<span class=\"pl-kos\">,<\/span> D1<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">arr2<\/span>: <span class=\"pl-kos\">[<\/span>A2<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-kos\">[<\/span>A1<span class=\"pl-kos\">,<\/span> B1<span class=\"pl-kos\">,<\/span> C1<span class=\"pl-kos\">,<\/span> D1<span class=\"pl-kos\">,<\/span> A2<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span>A1<span class=\"pl-kos\">,<\/span> B1<span class=\"pl-kos\">,<\/span> C1<span class=\"pl-kos\">,<\/span> D1<span class=\"pl-kos\">,<\/span> E1<span class=\"pl-kos\">,<\/span> A2<span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span class=\"pl-kos\">[<\/span>A1<span class=\"pl-kos\">,<\/span> B1<span class=\"pl-kos\">,<\/span> C1<span class=\"pl-kos\">,<\/span> D1<span class=\"pl-kos\">,<\/span> E1<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">arr2<\/span>: <span class=\"pl-kos\">[<\/span>A2<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-kos\">[<\/span>A1<span class=\"pl-kos\">,<\/span> B1<span class=\"pl-kos\">,<\/span> C1<span class=\"pl-kos\">,<\/span> D1<span class=\"pl-kos\">,<\/span> E1<span class=\"pl-kos\">,<\/span> A2<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span>A1<span class=\"pl-kos\">,<\/span> B1<span class=\"pl-kos\">,<\/span> C1<span class=\"pl-kos\">,<\/span> D1<span class=\"pl-kos\">,<\/span> E1<span class=\"pl-kos\">,<\/span> F1<span class=\"pl-kos\">,<\/span> A2<span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: <span class=\"pl-kos\">[<\/span>A1<span class=\"pl-kos\">,<\/span> B1<span class=\"pl-kos\">,<\/span> C1<span class=\"pl-kos\">,<\/span> D1<span class=\"pl-kos\">,<\/span> E1<span class=\"pl-kos\">,<\/span> F1<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">arr2<\/span>: <span class=\"pl-kos\">[<\/span>A2<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-kos\">[<\/span>A1<span class=\"pl-kos\">,<\/span> B1<span class=\"pl-kos\">,<\/span> C1<span class=\"pl-kos\">,<\/span> D1<span class=\"pl-kos\">,<\/span> E1<span class=\"pl-kos\">,<\/span> F1<span class=\"pl-kos\">,<\/span> A2<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>We hope it&#8217;s clear that this is getting unreasonable. Unfortunately you&#8217;d 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 &#8220;death by a thousand overloads&#8221;, and it doesn&#8217;t 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&#8217;d need an overload like the following:<\/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: #0000ff;\">function<\/span> <span class=\"pl-s1\">concat<\/span><span class=\"pl-c1\">&lt;<\/span>T<span class=\"pl-kos\">,<\/span> U<span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: T<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> U<span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: Array<span class=\"pl-kos\">&lt;<\/span>U<span class=\"pl-kos\">&gt;<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>But that signature doesn&#8217;t 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&#8217;t know the actual types we&#8217;re 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 &#8220;death by a thousand overloads&#8221; issue.<\/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: #0000ff;\">function<\/span> <span class=\"pl-en\">tail<\/span><span class=\"pl-c1\">&lt;<\/span>T <span style=\"color: #0000ff;\">extends<\/span> <span style=\"color: #0000ff;\">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 style=\"color: #0000ff;\">any<\/span><span class=\"pl-kos\">,<\/span> ...T<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #0000ff;\">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>\r\n    <span style=\"color: #0000ff;\">return<\/span> <span class=\"pl-s1\">rest<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span style=\"color: #0000ff;\">const<\/span> <span class=\"pl-s1\">myTuple<\/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 style=\"color: #09885a;\">3<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #09885a;\">4<\/span><span class=\"pl-kos\">]<\/span> <span style=\"color: #0000ff;\">as<\/span> <span class=\"pl-smi\">const<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #0000ff;\">const<\/span> <span class=\"pl-s1\">myArray<\/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;\">\/\/ type [2, 3, 4]<\/span>\r\n<span style=\"color: #0000ff;\">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>\r\n\r\n<span style=\"color: #148a14;\">\/\/ type [2, 3, ...string[]]<\/span>\r\n<span style=\"color: #0000ff;\">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 style=\"color: #0000ff;\">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 spread elements can occur anywhere in a tuple &#8211; not just 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 style=\"color: #0000ff;\">type<\/span> Strings <span class=\"pl-c1\">=<\/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-kos\">;<\/span>\r\n<span style=\"color: #0000ff;\">type<\/span> Numbers <span class=\"pl-c1\">=<\/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-kos\">;<\/span>\r\n\r\n<span style=\"color: #148a14;\">\/\/ [string, string, number, number]<\/span>\r\n<span style=\"color: #0000ff;\">type<\/span> StrStrNumNum <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span>...Strings<span class=\"pl-kos\">,<\/span> ...Numbers<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.\r\n<\/code><\/pre>\n<p>But now the language can flatten spreads at any position.<\/p>\n<p>When we spread in a type without a known length, the resulting type becomes unbounded as well, and all consecutive elements factor into the resulting rest element type.<\/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: #0000ff;\">type<\/span> Strings <span class=\"pl-c1\">=<\/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-kos\">;<\/span>\r\n<span style=\"color: #0000ff;\">type<\/span> Numbers <span class=\"pl-c1\">=<\/span> <span style=\"color: #0000ff;\">number<\/span><span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span>\r\n\r\n<span style=\"color: #148a14;\">\/\/ [string, string, ...Array&lt;number | boolean&gt;]<\/span>\r\n<span style=\"color: #0000ff;\">type<\/span> Unbounded <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span>...Strings<span class=\"pl-kos\">,<\/span> ...Numbers<span class=\"pl-kos\">,<\/span> <span style=\"color: #0000ff;\">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\" style=\"background-color: #f0f0f0; padding: 10px; border-radius: 10px;\"><span style=\"color: #0000ff;\">type<\/span> Arr <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>\r\n\r\n<span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-en\">concat<\/span><span class=\"pl-c1\">&lt;<\/span>T <span style=\"color: #0000ff;\">extends<\/span> Arr<span class=\"pl-kos\">,<\/span> U <span style=\"color: #0000ff;\">extends<\/span> Arr<span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arr1<\/span>: T<span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">arr2<\/span>: U<span class=\"pl-kos\">)<\/span>: <span class=\"pl-kos\">[<\/span>...T<span class=\"pl-kos\">,<\/span> ...U<span class=\"pl-kos\">]<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #0000ff;\">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>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>While that one signature is still a bit lengthy, it&#8217;s still only one signature, it only has to be written once, and it actually gives predictable behavior on all arrays and tuples.<\/p>\n<p>This functionality on its own is great, but there are other 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 along with the initial few arguments that that function expects. It then returns a new function that takes any other arguments the function needs, and calls them together.<\/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 style=\"color: #0000ff;\">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>\r\n    <span style=\"color: #0000ff;\">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>\r\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 &#8220;just work&#8221;.<\/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: #0000ff;\">type<\/span> Arr <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>\r\n\r\n<span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-en\">partialCall<\/span><span class=\"pl-c1\">&lt;<\/span>T <span style=\"color: #0000ff;\">extends<\/span> Arr<span class=\"pl-kos\">,<\/span> U <span style=\"color: #0000ff;\">extends<\/span> Arr<span class=\"pl-kos\">,<\/span> R<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>...T<span class=\"pl-kos\">,<\/span> ...U<span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-c1\">=&gt;<\/span> R<span class=\"pl-kos\">,<\/span> ...<span class=\"pl-s1\">headArgs<\/span>: T<span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #0000ff;\">return<\/span> <span class=\"pl-kos\">(<\/span>...<span class=\"pl-s1\">b<\/span>: U<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\">b<\/span><span class=\"pl-kos\">)<\/span>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>In this case, <code>partialCall<\/code> understands which parameters it can and can&#8217;t 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\" style=\"background-color: #f0f0f0; padding: 10px; border-radius: 10px;\"><span style=\"color: #0000ff;\">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 style=\"color: #0000ff;\">string<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">y<\/span>: <span style=\"color: #0000ff;\">number<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">z<\/span>: <span style=\"color: #0000ff;\">boolean<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-c1\">=&gt;<\/span> <span class=\"pl-kos\">{<\/span><span class=\"pl-kos\">}<\/span>\r\n\r\n<span style=\"color: #148a14;\">\/\/ This doesn't work because we're feeding in the wrong type for 'x'.<\/span>\r\n<span style=\"color: #0000ff;\">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 style=\"color: #09885a;\">100<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #148a14;\">\/\/                          ~~~<\/span>\r\n<span style=\"color: #148a14;\">\/\/ error! Argument of type 'number' is not assignable to parameter of type 'string'.<\/span>\r\n\r\n\r\n<span style=\"color: #148a14;\">\/\/ This doesn't work because we're passing in too many arguments.<\/span>\r\n<span style=\"color: #0000ff;\">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 style=\"color: #a31515;\">\"hello\"<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #09885a;\">100<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #0000ff;\">true<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #a31515;\">\"oops\"<\/span><span class=\"pl-kos\">)<\/span>\r\n<span style=\"color: #148a14;\">\/\/                                              ~~~~~~<\/span>\r\n<span style=\"color: #148a14;\">\/\/ error! Expected 4 arguments, but got 5.<\/span>\r\n\r\n\r\n<span style=\"color: #148a14;\">\/\/ This works! It has the type '(y: number, z: boolean) =&gt; void'<\/span>\r\n<span style=\"color: #0000ff;\">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 style=\"color: #a31515;\">\"hello\"<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #148a14;\">\/\/ What can we do with f3 now?<\/span>\r\n\r\n<span class=\"pl-en\">f3<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #09885a;\">123<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #0000ff;\">true<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span> <span style=\"color: #148a14;\">\/\/ works!<\/span>\r\n\r\n<span class=\"pl-en\">f3<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #148a14;\">\/\/ error! Expected 2 arguments, but got 0.<\/span>\r\n\r\n<span class=\"pl-en\">f3<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #09885a;\">123<\/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 style=\"color: #148a14;\">\/\/      ~~~~~~~<\/span>\r\n<span style=\"color: #148a14;\">\/\/ error! Argument of type '\"hello\"' 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&#8217;s built-in <code>bind<\/code> method. A handful of other inference improvements and patterns also went into this, and if you&#8217;re 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><a name=\"labeled-tuple-elements\"><\/a> 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 &#8211; 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&#8230;<\/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: #0000ff;\">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 style=\"color: #0000ff;\">string<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #0000ff;\">number<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-smi\"><span style=\"color: #0000ff;\">void<\/span><\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #148a14;\">\/\/ ...<\/span>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>&#8230;should appear no different from the following function&#8230;<\/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: #0000ff;\">function<\/span> <span class=\"pl-en\">foo<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">arg0<\/span>: <span style=\"color: #0000ff;\">string<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">arg1<\/span>: <span style=\"color: #0000ff;\">number<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-smi\"><span style=\"color: #0000ff;\">void<\/span><\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #148a14;\">\/\/ ...<\/span>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>&#8230;for any caller of <code>foo<\/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-en\">foo<\/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 class=\"pl-kos\">;<\/span> <span style=\"color: #148a14;\">\/\/ works<\/span>\r\n\r\n<span class=\"pl-en\">foo<\/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> <span style=\"color: #148a14;\">\/\/ error<\/span>\r\n<span class=\"pl-en\">foo<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #a31515;\">\"hello\"<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span> <span style=\"color: #148a14;\">\/\/ 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 &#8211; harder to communicate our intent.<\/p>\n<p>That&#8217;s 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\" style=\"background-color: #f0f0f0; padding: 10px; border-radius: 10px;\"><span style=\"color: #0000ff;\">type<\/span> Range <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>Further pushing the connection between parameter lists and tuple types, we&#8217;ve made the syntax for rest elements and optional elements mirror that of parameter lists.<\/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: #0000ff;\">type<\/span> Foo <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>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\" style=\"background-color: #f0f0f0; padding: 10px; border-radius: 10px;\"><span style=\"color: #0000ff;\">type<\/span> Bar <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">[<\/span><span class=\"pl-smi\">first<\/span>: string<span class=\"pl-kos\">,<\/span> <span style=\"color: #0000ff;\">number<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #148a14;\">\/\/                         ~~~~~~<\/span>\r\n<span style=\"color: #148a14;\">\/\/ error! Tuple members must all have names or all not have names.<\/span><\/pre>\n<\/div>\n<p>It&#8217;s worth noting &#8211; labels don&#8217;t require us to name our variables differently when destructuring. They&#8217;re purely there for documentation and tooling.<\/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: #0000ff;\">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 style=\"color: #0000ff;\">string<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-s1\">second<\/span>: <span style=\"color: #0000ff;\">number<\/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\r\n    <span style=\"color: #148a14;\">\/\/ note: we didn't need to name these 'first' and 'second'<\/span>\r\n    <span style=\"color: #0000ff;\">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>\r\n\r\n    <span style=\"color: #148a14;\">\/\/ ...<\/span>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>On the whole, labeled tuples are handy when taking advantage of patterns around tuples and argument lists, along with implementing overloads in a type-safe way. 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><a name=\"class-property-inference\"><\/a> 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\" style=\"background-color: #f0f0f0; padding: 10px; border-radius: 10px;\"><span style=\"color: #0000ff;\">class<\/span> Square <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #148a14;\">\/\/ Previously: implicit any!<\/span>\r\n    <span style=\"color: #148a14;\">\/\/ Now: inferred to `number`!<\/span>\r\n    <span class=\"pl-c1\">area<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-c1\">sideLength<\/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 style=\"color: #0000ff;\">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 style=\"color: #09885a;\">2<\/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>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\" style=\"background-color: #f0f0f0; padding: 10px; border-radius: 10px;\"><span style=\"color: #0000ff;\">class<\/span> Square <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-c1\">sideLength<\/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;\">if<\/span> <span class=\"pl-kos\">(<\/span>Math<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>\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    <span class=\"pl-kos\">}<\/span>\r\n\r\n    <span style=\"color: #0000ff;\">get<\/span> <span class=\"pl-en\">area<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n        <span style=\"color: #0000ff;\">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 style=\"color: #148a14;\">\/\/     ~~~~~~~~~~~~~~~<\/span>\r\n        <span style=\"color: #148a14;\">\/\/ error! Object is possibly 'undefined'.<\/span>\r\n    <span class=\"pl-kos\">}<\/span>\r\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&#8217;ll need an explicit type annotation along with a definite assignment assertion (<code>!<\/code>) if you&#8217;re in <code>strictPropertyInitialization<\/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: #0000ff;\">class<\/span> Square <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #148a14;\">\/\/ definite assignment assertion<\/span>\r\n    <span style=\"color: #148a14;\">\/\/        v<\/span>\r\n    <span class=\"pl-c1\">sideLength<\/span>!: <span style=\"color: #0000ff;\">number<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span style=\"color: #148a14;\">\/\/         ^^^^^^^^<\/span>\r\n    <span style=\"color: #148a14;\">\/\/ type annotation<\/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-en\">initialize<\/span><span class=\"pl-kos\">(<\/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\">initialize<\/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 style=\"color: #0000ff;\">get<\/span> <span class=\"pl-en\">area<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n        <span style=\"color: #0000ff;\">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><\/pre>\n<\/div>\n<h2><a name=\"short-circuiting-assignment-operators\"><\/a> 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\" style=\"background-color: #f0f0f0; padding: 10px; border-radius: 10px;\"><span style=\"color: #148a14;\">\/\/ Addition<\/span>\r\n<span style=\"color: #148a14;\">\/\/ a = a + b<\/span>\r\n<span class=\"pl-s1\">a<\/span> <span class=\"pl-c1\">+=<\/span> <span class=\"pl-s1\">b<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #148a14;\">\/\/ Subtraction<\/span>\r\n<span style=\"color: #148a14;\">\/\/ a = a - b<\/span>\r\n<span class=\"pl-s1\">a<\/span> <span class=\"pl-c1\">-=<\/span> <span class=\"pl-s1\">b<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #148a14;\">\/\/ Multiplication<\/span>\r\n<span style=\"color: #148a14;\">\/\/ a = a * b<\/span>\r\n<span class=\"pl-s1\">a<\/span> *= <span class=\"pl-s1\">b<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #148a14;\">\/\/ Division<\/span>\r\n<span style=\"color: #148a14;\">\/\/ a = a \/ b<\/span>\r\n<span class=\"pl-s1\">a<\/span> \/= <span class=\"pl-s1\">b<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #148a14;\">\/\/ Exponentiation<\/span>\r\n<span style=\"color: #148a14;\">\/\/ a = a ** b<\/span>\r\n<span class=\"pl-s1\">a<\/span> **= <span class=\"pl-s1\">b<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #148a14;\">\/\/ Left Bit Shift<\/span>\r\n<span style=\"color: #148a14;\">\/\/ a = a &lt;&lt; b<\/span>\r\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! But there are 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&#8217;s why TypeScript 4.0 supports a promising proposal 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\" style=\"background-color: #f0f0f0; padding: 10px; border-radius: 10px;\"><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>\r\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>\r\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>There are even some patterns we&#8217;ve seen (or, uh, written ourselves) to lazily initialize values when they&#8217;ll be needed.<\/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: #0000ff;\">let<\/span> <span class=\"pl-s1\">values<\/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;\">\/\/ Before<\/span>\r\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 style=\"color: #a31515;\">\"hello\"<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #148a14;\">\/\/ After<\/span>\r\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 style=\"color: #a31515;\">\"hello\"<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>(look, we&#8217;re not proud of <em>all<\/em> the code we write&#8230;)<\/p>\n<p>On the rare case that you use getters or setters with side-effects, it&#8217;s worth noting that these operators only perform assignments if necessary. In that sense, the assignment is <em>short-circuited<\/em>, which is the only way they differ from other compound assignments.<\/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\">a<\/span> <span class=\"pl-c1\">||<\/span><span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">b<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #148a14;\">\/\/ actually equivalent to<\/span>\r\n\r\n<span class=\"pl-s1\">a<\/span> <span class=\"pl-c1\">||<\/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><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>We&#8217;d 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&#8217;s proposal repository for this feature<\/a>.<\/p>\n<h2><a name=\"unknown-on-catch\"><\/a> <code>unknown<\/code> on <code>catch<\/code> Clause Bindings<\/h2>\n<p>Since the beginning days of TypeScript, <code>catch<\/code> clause variables were always 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\" style=\"background-color: #f0f0f0; padding: 10px; border-radius: 10px;\"><span style=\"color: #0000ff;\">try<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #148a14;\">\/\/ ...<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n<span style=\"color: #0000ff;\">catch<\/span> <span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">x<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #148a14;\">\/\/ x has type 'any' - have fun!<\/span>\r\n    <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>\r\n    <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>\r\n    <span class=\"pl-s1\">x<\/span><span class=\"pl-c1\">++<\/span><span class=\"pl-kos\">;<\/span>\r\n    <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>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>The above has some undesirable behavior if we&#8217;re trying to prevent <em>more<\/em> errors from accidentally happening in our error-handling code! Because these variables have the type <code>any<\/code> by default, they lack any type-safety which could prevent invalid operations.<\/p>\n<p>That&#8217;s 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\" style=\"background-color: #f0f0f0; padding: 10px; border-radius: 10px;\"><span style=\"color: #0000ff;\">try<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #148a14;\">\/\/ ...<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n<span style=\"color: #0000ff;\">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>\r\n    <span style=\"color: #148a14;\">\/\/ error!<\/span>\r\n    <span style=\"color: #148a14;\">\/\/ Property 'toUpperCase' does not exist on type 'unknown'.<\/span>\r\n    <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>\r\n\r\n    <span style=\"color: #0000ff;\">if<\/span> <span class=\"pl-kos\">(<\/span><span style=\"color: #0000ff;\">typeof<\/span> <span class=\"pl-s1\">e<\/span> <span class=\"pl-c1\">===<\/span> <span style=\"color: #a31515;\">\"string\"<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n        <span style=\"color: #148a14;\">\/\/ works!<\/span>\r\n        <span style=\"color: #148a14;\">\/\/ We've narrowed 'e' down to the type 'string'.<\/span>\r\n        <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>\r\n    <span class=\"pl-kos\">}<\/span>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>While the types of <code>catch<\/code> variables won&#8217;t 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><a name=\"custom-jsx-factories\"><\/a> 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&#8217;t 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 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\" style=\"background-color: #f0f0f0; padding: 10px; border-radius: 10px;\"><span class=\"pl-kos\">{<\/span>\r\n  <span style=\"color: #a31515;\">\"compilerOptions\"<\/span>: <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #a31515;\">\"target\"<\/span>: <span style=\"color: #a31515;\">\"esnext\"<\/span><span class=\"pl-kos\">,<\/span>\r\n    <span style=\"color: #a31515;\">\"module\"<\/span>: <span style=\"color: #a31515;\">\"commonjs\"<\/span><span class=\"pl-kos\">,<\/span>\r\n    <span style=\"color: #a31515;\">\"jsx\"<\/span>: <span style=\"color: #a31515;\">\"react\"<\/span><span class=\"pl-kos\">,<\/span>\r\n    <span style=\"color: #a31515;\">\"jsxFactory\"<\/span>: <span style=\"color: #a31515;\">\"h\"<\/span><span class=\"pl-kos\">,<\/span>\r\n    <span style=\"color: #a31515;\">\"jsxFragmentFactory\"<\/span>: <span style=\"color: #a31515;\">\"Fragment\"<\/span>\r\n  <span class=\"pl-kos\">}<\/span>\r\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&#8230;<\/p>\n<div class=\"highlight highlight-source-tsx\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0; padding: 10px; border-radius: 10px;\"><span style=\"color: #148a14;\">\/\/ Note: these pragma comments need to be written<\/span>\r\n<span style=\"color: #148a14;\">\/\/ with a JSDoc-style multiline syntax to take effect.<\/span>\r\n<span style=\"color: #148a14;\">\/** <span class=\"pl-k\">@jsx<\/span> h *\/<\/span>\r\n<span style=\"color: #148a14;\">\/** <span class=\"pl-k\">@jsxFrag<\/span> Fragment *\/<\/span>\r\n\r\n<span style=\"color: #0000ff;\">import<\/span> <span class=\"pl-kos\">{<\/span> <span class=\"pl-s1\">h<\/span><span class=\"pl-kos\">,<\/span> Fragment <span class=\"pl-kos\">}<\/span> <span style=\"color: #0000ff;\">from<\/span> <span style=\"color: #a31515;\">\"preact\"<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #0000ff;\">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>\r\n    <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>\r\n<span class=\"pl-c1\">&lt;<\/span>\/<span class=\"pl-c1\">&gt;<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>&#8230;will get transformed to this output JavaScript&#8230;<\/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 style=\"color: #148a14;\">\/\/ Note: these pragma comments need to be written<\/span>\r\n<span style=\"color: #148a14;\">\/\/ with a JSDoc-style multiline syntax to take effect.<\/span>\r\n<span style=\"color: #148a14;\">\/** <span class=\"pl-k\">@jsx<\/span> h *\/<\/span>\r\n<span style=\"color: #148a14;\">\/** <span class=\"pl-k\">@jsxFrag<\/span> Fragment *\/<\/span>\r\n<span style=\"color: #0000ff;\">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 style=\"color: #0000ff;\">from<\/span> <span style=\"color: #a31515;\">\"preact\"<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #0000ff;\">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> null<span class=\"pl-kos\">,<\/span>\r\n    <span class=\"pl-en\">h<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #a31515;\">\"div\"<\/span><span class=\"pl-kos\">,<\/span> null<span class=\"pl-kos\">,<\/span> <span style=\"color: #a31515;\">\"Hello\"<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>We&#8217;d 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><a name=\"build-and-noemitonerror\"><\/a> 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><a name=\"noemit-and-incremental\"><\/a> <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><a name=\"editor-improvements\"><\/a> Editor Improvements<\/h2>\n<p>The TypeScript compiler doesn&#8217;t only power the editing experience for TypeScript itself in most major editors &#8211; 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 &#8211; 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<ul>\n<li>Visual Studio Code supports <a href=\"https:\/\/code.visualstudio.com\/docs\/typescript\/typescript-compiling#_using-the-workspace-version-of-typescript\" rel=\"nofollow\">selecting different versions of TypeScript<\/a>. Alternatively, there&#8217;s the <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=ms-vscode.vscode-typescript-next\" rel=\"nofollow\">JavaScript\/TypeScript Nightly Extension<\/a> to stay on the bleeding edge (which is typically very stable).<\/li>\n<li>Visual Studio 2017\/2019 have [the SDK installers above] and <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.TypeScript.MSBuild\" rel=\"nofollow\">MSBuild installs<\/a>.<\/li>\n<li>Sublime Text 3 supports <a href=\"https:\/\/github.com\/microsoft\/TypeScript-Sublime-Plugin#note-using-different-versions-of-typescript\">selecting different versions of TypeScript<\/a><\/li>\n<\/ul>\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><a name=\"deprecated-support\"><\/a> <code>\/** @deprecated *\/<\/code> Support<\/h3>\n<p>TypeScript&#8217;s 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:\/\/devblogs.microsoft.com\/typescript\/wp-content\/uploads\/sites\/11\/2020\/06\/deprecated_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><a name=\"partial-editing-mode\"><\/a> Partial Editing Mode at Startup<\/h3>\n<p>One specific piece of feedback we&#8217;ve heard from users has been slow startup times, especially on bigger projects. Specifically, the culprit is usually a process called <em>project loading<\/em>, which is roughly the same as the <em>program construction<\/em> step of our compiler. This is the process of starting with an initial set of files, parsing them, resolving their dependencies, parsing those dependencies, resolving those dependencies&#8217; dependencies, and so on. It ends up taking quite a bit of time. The the bigger your project is, the worse the startup delays you might experience before you can get basic editor operations like go-to-definition, code completions, and quick info.<\/p>\n<p>That&#8217;s why we&#8217;ve 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 has a single-file view of the world. This has always been an option for editors, but TypeScript 4.0 expands the functionality to semantic operations (as opposed to just syntactic operations). While that means the server has limited information (so not every operation will be totally complete) &#8211; this is often good enough for some basic code completion, quick info, signature help, and go-to-definition when you first open up your editor.<\/p>\n<p>While it&#8217;s hard to pin down precisely what sorts of improvements you&#8217;ll see based on hardware, operating system, and project size; but today we&#8217;ve seen machines take anywhere between <em>20 seconds to a minute<\/em> until TypeScript is responsive on a file in the Visual Studio Code codebase. In contrast, this new mode seems to bring the time until TypeScript is interactive on that codebase <strong>down to anywhere between 2-5 seconds<\/strong>.<\/p>\n<p>Currently the only editor that supports this mode is <a href=\"http:\/\/code.visualstudio.com\/insiders\" rel=\"nofollow\">Visual Studio Code Insiders<\/a>, and you can try it out by following these steps.<\/p>\n<ol>\n<li>installing <a href=\"http:\/\/code.visualstudio.com\/insiders\" rel=\"nofollow\">Visual Studio Code Insiders<\/a><\/li>\n<li><a href=\"https:\/\/code.visualstudio.com\/docs\/typescript\/typescript-compiling#_using-newer-typescript-versions\" rel=\"nofollow\">configuring Visual Studio Code Insiders<\/a> to use the beta, or installing the <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=ms-vscode.vscode-typescript-next\" rel=\"nofollow\">JavaScript and TypeScript Nightly Extension<\/a> for Visual Studio Code Insiders.<\/li>\n<li>opening your JSON settings view: <code>&gt; Preferences: Open Settings (JSON)<\/code><\/li>\n<li>adding the following lines:\n<pre><code>\/\/ The editor will say 'dynamic' is an unknown option,\r\n\/\/ but don't worry about it for now. It's still experimental.\r\n\"typescript.tsserver.useSeparateSyntaxServer\": \"dynamic\",\r\n<\/code><\/pre>\n<\/li>\n<\/ol>\n<p>There&#8217;s still room for improvement in UX and functionality &#8211; both from the editor side and the language support side. For example, while partial editing support is already loaded and working, you&#8217;ll still see <code>Initializing JS\/TS language features<\/code> in your status bar. You can ignore that since operations will still be powered by that partial mode. We also have <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/issues\/39035\">a list of improvements<\/a> in the works, and we&#8217;re 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><a name=\"smarter-auto-imports\"><\/a> Smarter Auto-Imports<\/h3>\n<p>Auto-import is a fantastic feature that makes coding a lot easier; however, every time auto-import doesn&#8217;t seem to work, it throws us off a lot and can ruin our productivity. One specific issue that we heard from users was that auto-imports wouldn&#8217;t work on packages that were written in TypeScript &#8211; that is, until they wrote at least one explicit import somewhere else in their project.<\/p>\n<p>Now, that sounds pretty weird and oddly specific. 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 are powered by checking which packages your project <em>already<\/em> includes. TypeScript has a quirk to make some scenarios work better by automatically including all packages in <code>node_modules\/@types<\/code>, but not other packages &#8211; the rationale being crawling through all your <code>node_modules<\/code> packages might be <strong>expensive<\/strong>.<\/p>\n<p>All of this leads to a pretty lousy getting started experience for when you&#8217;re trying to auto-import something that you&#8217;ve just installed but haven&#8217;t used yet.<\/p>\n<p>TypeScript 4.0 now does a little extra work in editor scenarios to include any packages you&#8217;ve listed in your <code>package.json<\/code>&#8216;s <code>dependencies<\/code> field. The information from these packages is only used to improve auto-imports, and doesn&#8217;t change anything else like type-checking. This helps alleviate the cost of walking through your <code>node_modules<\/code> directories while still fixing one of the most common problems we&#8217;ve heard for new projects.<\/p>\n<p>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><a name=\"breaking-changes\"><\/a> Breaking Changes<\/h2>\n<h3><code>lib.d.ts<\/code> Changes<\/h3>\n<p>Our <code>lib.d.ts<\/code> declarations have changed &#8211; 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>Properties Overridding 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\" style=\"background-color: #f0f0f0; padding: 10px; border-radius: 10px;\"><span style=\"color: #0000ff;\">class<\/span> Base <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #0000ff;\">get<\/span> <span class=\"pl-en\">foo<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n        <span style=\"color: #0000ff;\">return<\/span> <span style=\"color: #09885a;\">100<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-kos\">}<\/span>\r\n    <span style=\"color: #0000ff;\">set<\/span> <span class=\"pl-en\">foo<\/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\r\n<span style=\"color: #0000ff;\">class<\/span> Derived <span style=\"color: #0000ff;\">extends<\/span> Base <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-c1\">foo<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #09885a;\">10<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #148a14;\">\/\/  ~~~<\/span>\r\n<span style=\"color: #148a14;\">\/\/ error!<\/span>\r\n<span style=\"color: #148a14;\">\/\/ 'foo' is defined as an accessor in class 'Base',<\/span>\r\n<span style=\"color: #148a14;\">\/\/ but is overridden here in 'Derived' as an instance property.<\/span>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\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: #0000ff;\">class<\/span> Base <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-c1\">prop<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #09885a;\">10<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span style=\"color: #0000ff;\">class<\/span> Derived <span style=\"color: #0000ff;\">extends<\/span> Base <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #0000ff;\">get<\/span> <span class=\"pl-en\">prop<\/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 style=\"color: #148a14;\">\/\/ error!<\/span>\r\n    <span style=\"color: #148a14;\">\/\/ 'prop' is defined as a property in class 'Base', but is overridden here in 'Derived' as an accessor.<\/span>\r\n        <span style=\"color: #0000ff;\">return<\/span> <span style=\"color: #09885a;\">100<\/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>See more details on <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/37894\">the implementing pull request<\/a>.<\/p>\n<h3>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\" style=\"background-color: #f0f0f0; padding: 10px; border-radius: 10px;\"><span style=\"color: #0000ff;\">interface<\/span> Thing <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-c1\">prop<\/span>: <span style=\"color: #0000ff;\">string<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-en\">f<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">x<\/span>: Thing<span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #0000ff;\">delete<\/span> <span class=\"pl-s1\">x<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">prop<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span style=\"color: #148a14;\">\/\/     ~~~~~~<\/span>\r\n    <span style=\"color: #148a14;\">\/\/ error! The operand of a 'delete' operator must be optional.<\/span>\r\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>Usage of TypeScript&#8217;s Node Factory is Deprecated<\/h3>\n<p>Today TypeScript provides a set of &#8220;factory&#8221; functions for producing AST Nodes; however, TypeScript 4.0 provides a new node factory API. As a result, for TypeScript 4.0 we&#8217;ve 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>What&#8217;s Next?<\/h2>\n<p>As with all of our beta releases, we&#8217;re looking for users to try things out, upgrade a few projects, stress test the release, and give us your feedback! We want to make sure TypeScript 4.0 really hits the mark and makes migration easy, so try it out and <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/issues\">give us your feedback<\/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 release the beta of the next major milestone in the TypeScript programming language: TypeScript 4.0. This beta takes us on our first step into TypeScript 4.0, and while it brings a new major version, don&#8217;t fret &#8211; there are no substantially larger breaking changes than usual. Our philosophy in evolving TypeScript [&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-2633","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-typescript"],"acf":[],"blog_post_summary":"<p>Today we&#8217;re excited to release the beta of the next major milestone in the TypeScript programming language: TypeScript 4.0. This beta takes us on our first step into TypeScript 4.0, and while it brings a new major version, don&#8217;t fret &#8211; there are no substantially larger breaking changes than usual. Our philosophy in evolving TypeScript [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/2633","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=2633"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/2633\/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=2633"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/categories?post=2633"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/tags?post=2633"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}