{"id":3513,"date":"2022-08-11T11:06:20","date_gmt":"2022-08-11T19:06:20","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/typescript\/?p=3513"},"modified":"2022-08-11T11:06:20","modified_gmt":"2022-08-11T19:06:20","slug":"announcing-typescript-4-8-rc","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-4-8-rc\/","title":{"rendered":"Announcing TypeScript 4.8 RC"},"content":{"rendered":"<p>Today we&#8217;re excited to announce our Release Candidate (RC) of TypeScript 4.8.\nBetween now and the stable release of TypeScript 4.8, we expect no further changes apart from critical bug fixes.<\/p>\n<p>To get started using the RC, you can get it <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.TypeScript.MSBuild\">through NuGet<\/a>, or use npm with the following command:<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span style=\"color: #000000;\">npm install -D typescript@rc<\/span>\r\n<\/code><\/pre>\n<p>You can also get editor support by<\/p>\n<ul>\n<li><a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=TypeScriptTeam.TypeScript-48rc\">Downloading for Visual Studio 2022\/2019<\/a><\/li>\n<li>Following directions for <a href=\"https:\/\/code.visualstudio.com\/Docs\/languages\/typescript#_using-newer-typescript-versions\">Visual Studio Code<\/a>.<\/li>\n<\/ul>\n<p>Here&#8217;s a quick list of what&#8217;s new in TypeScript 4.8!<\/p>\n<ul>\n<li><a href=\"#smarter-type-narrowing-and-simplifications\">Improved Intersection Reduction, Union Compatibility, and Narrowing<\/a><\/li>\n<li><a href=\"#infer-types-template-strings\">Improved Inference for <code>infer<\/code> Types in Template String Types<\/a><\/li>\n<li><a href=\"#build-watch-incremental-improvements\"><code>--build<\/code>, <code>--watch<\/code>, and <code>--incremental<\/code> Performance Improvements<\/a><\/li>\n<li><a href=\"#object-array-comparison-errors\">Errors When Comparing Object and Array Literals<\/a><\/li>\n<li><a href=\"#inference-binding-patterns\">Improved Inference from Binding Patterns<\/a><\/li>\n<li><a href=\"#file-watching-fixes\">File-Watching Fixes (Especially Across <code>git checkout<\/code>s)<\/a><\/li>\n<li><a href=\"#find-all-refs-improvements\">Find-All-References Performance Improvements<\/a><\/li>\n<li><a href=\"#exclude-globs-auto-import\">Exclude Specific Files from Auto-Imports<\/a><\/li>\n<li><a href=\"#correctness-changes\">Correctness Fixes and Breaking Changes<\/a><\/li>\n<\/ul>\n<h2><a name=\"beta-delta\"><\/a> What&#8217;s New Since the Beta?<\/h2>\n<p>Since our <a href=\"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-4-8-beta\/\">beta release<\/a>, the RC now has <a href=\"#exclude-globs-auto-import\">support for excluding which files are considered in auto-imports<\/a>.\nThe beta release post also did not document a break around unused destructuring aliases in type signatures, which is now detailed in our <a href=\"#correctness-changes\">Correctness Fixes and Breaking Changes section<\/a>.<\/p>\n<h2><a name=\"smarter-type-narrowing-and-simplifications\"><\/a> Improved Intersection Reduction, Union Compatibility, and Narrowing<\/h2>\n<p>TypeScript 4.8 brings a series of correctness and consistency improvements under <code>--strictNullChecks<\/code>.\nThese changes affect how intersection and union types work, and are leveraged in how TypeScript narrows types.<\/p>\n<p>For example, <code>unknown<\/code> is close in spirit to the union type <code>{} | null | undefined<\/code> because it accepts <code>null<\/code>, <code>undefined<\/code>, and any other type.\nTypeScript now recognizes this, and allows assignments from <code>unknown<\/code> to <code>{} | null | undefined<\/code>.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span style=\"color: #0000FF;\">function<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #795E26;\">f<\/span><span style=\"color: #000000;\">(<\/span><span style=\"color: #001080;\">x<\/span><span style=\"color: #000000;\">: <\/span><span style=\"color: #267F99;\">unknown<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #001080;\">y<\/span><span style=\"color: #000000;\">: {} | <\/span><span style=\"color: #267F99;\">null<\/span><span style=\"color: #000000;\"> | <\/span><span style=\"color: #267F99;\">undefined<\/span><span style=\"color: #000000;\">) {<\/span>\r\n<span style=\"color: #000000;\">    <\/span><span style=\"color: #001080;\">x<\/span><span style=\"color: #000000;\"> = <\/span><span style=\"color: #001080;\">y<\/span><span style=\"color: #000000;\">; <\/span><span style=\"color: #008000;\">\/\/ always worked<\/span>\r\n<span style=\"color: #000000;\">    <\/span><span style=\"color: #001080;\">y<\/span><span style=\"color: #000000;\"> = <\/span><span style=\"color: #001080;\">x<\/span><span style=\"color: #000000;\">; <\/span><span style=\"color: #008000;\">\/\/ used to error, now works<\/span>\r\n<span style=\"color: #000000;\">}<\/span>\r\n<\/code><\/pre>\n<p>Another change is that <code>{}<\/code> intersected with any other object type simplifies right down to that object type.\nThat meant that we were able to rewrite <code>NonNullable<\/code> to just use an intersection with <code>{}<\/code>, because <code>{} &amp; null<\/code> and <code>{} &amp; undefined<\/code> just get tossed away.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span style=\"color: #A31515;\">- type NonNullable&lt;T&gt; = T extends null | undefined ? never : T;<\/span>\r\n<span style=\"color: #098658;\">+ type NonNullable&lt;T&gt; = T &amp; {};<\/span>\r\n<\/code><\/pre>\n<p>This is an improvement because intersection types like this can be reduced and assigned to, while conditional types currently cannot.\nSo <code>NonNullable&lt;NonNullable&lt;T&gt;&gt;<\/code> now simplifies at least to <code>NonNullable&lt;T&gt;<\/code>, whereas it didn&#8217;t before.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span style=\"color: #0000FF;\">function<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #795E26;\">foo<\/span><span style=\"color: #000000;\">&lt;<\/span><span style=\"color: #267F99;\">T<\/span><span style=\"color: #000000;\">&gt;(<\/span><span style=\"color: #001080;\">x<\/span><span style=\"color: #000000;\">: <\/span><span style=\"color: #267F99;\">NonNullable<\/span><span style=\"color: #000000;\">&lt;<\/span><span style=\"color: #267F99;\">T<\/span><span style=\"color: #000000;\">&gt;, <\/span><span style=\"color: #001080;\">y<\/span><span style=\"color: #000000;\">: <\/span><span style=\"color: #267F99;\">NonNullable<\/span><span style=\"color: #000000;\">&lt;<\/span><span style=\"color: #267F99;\">NonNullable<\/span><span style=\"color: #000000;\">&lt;<\/span><span style=\"color: #267F99;\">T<\/span><span style=\"color: #000000;\">&gt;&gt;) {<\/span>\r\n<span style=\"color: #000000;\">    <\/span><span style=\"color: #001080;\">x<\/span><span style=\"color: #000000;\"> = <\/span><span style=\"color: #001080;\">y<\/span><span style=\"color: #000000;\">; <\/span><span style=\"color: #008000;\">\/\/ always worked<\/span>\r\n<span style=\"color: #000000;\">    <\/span><span style=\"color: #001080;\">y<\/span><span style=\"color: #000000;\"> = <\/span><span style=\"color: #001080;\">x<\/span><span style=\"color: #000000;\">; <\/span><span style=\"color: #008000;\">\/\/ used to error, now works<\/span>\r\n<span style=\"color: #000000;\">}<\/span>\r\n<\/code><\/pre>\n<p>These changes also allowed us to bring in sensible improvements in control flow analysis and type narrowing.\nFor example, <code>unknown<\/code> is now narrowed just like <code>{} | null | undefined<\/code> in truthy branches.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span style=\"color: #0000FF;\">function<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #795E26;\">narrowUnknownishUnion<\/span><span style=\"color: #000000;\">(<\/span><span style=\"color: #001080;\">x<\/span><span style=\"color: #000000;\">: {} | <\/span><span style=\"color: #267F99;\">null<\/span><span style=\"color: #000000;\"> | <\/span><span style=\"color: #267F99;\">undefined<\/span><span style=\"color: #000000;\">) {<\/span>\r\n<span style=\"color: #000000;\">    <\/span><span style=\"color: #AF00DB;\">if<\/span><span style=\"color: #000000;\"> (<\/span><span style=\"color: #001080;\">x<\/span><span style=\"color: #000000;\">) {<\/span>\r\n<span style=\"color: #000000;\">        <\/span><span style=\"color: #001080;\">x<\/span><span style=\"color: #000000;\">;  <\/span><span style=\"color: #008000;\">\/\/ {}<\/span>\r\n<span style=\"color: #000000;\">    }<\/span>\r\n<span style=\"color: #000000;\">    <\/span><span style=\"color: #AF00DB;\">else<\/span><span style=\"color: #000000;\"> {<\/span>\r\n<span style=\"color: #000000;\">        <\/span><span style=\"color: #001080;\">x<\/span><span style=\"color: #000000;\">;  <\/span><span style=\"color: #008000;\">\/\/ {} | null | undefined<\/span>\r\n<span style=\"color: #000000;\">    }<\/span>\r\n<span style=\"color: #000000;\">}<\/span>\r\n\r\n<span style=\"color: #0000FF;\">function<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #795E26;\">narrowUnknown<\/span><span style=\"color: #000000;\">(<\/span><span style=\"color: #001080;\">x<\/span><span style=\"color: #000000;\">: <\/span><span style=\"color: #267F99;\">unknown<\/span><span style=\"color: #000000;\">) {<\/span>\r\n<span style=\"color: #000000;\">    <\/span><span style=\"color: #AF00DB;\">if<\/span><span style=\"color: #000000;\"> (<\/span><span style=\"color: #001080;\">x<\/span><span style=\"color: #000000;\">) {<\/span>\r\n<span style=\"color: #000000;\">        <\/span><span style=\"color: #001080;\">x<\/span><span style=\"color: #000000;\">;  <\/span><span style=\"color: #008000;\">\/\/ used to be 'unknown', now '{}'<\/span>\r\n<span style=\"color: #000000;\">    }<\/span>\r\n<span style=\"color: #000000;\">    <\/span><span style=\"color: #AF00DB;\">else<\/span><span style=\"color: #000000;\"> {<\/span>\r\n<span style=\"color: #000000;\">        <\/span><span style=\"color: #001080;\">x<\/span><span style=\"color: #000000;\">;  <\/span><span style=\"color: #008000;\">\/\/ unknown<\/span>\r\n<span style=\"color: #000000;\">    }<\/span>\r\n<span style=\"color: #000000;\">}<\/span>\r\n<\/code><\/pre>\n<p>Generic values also get narrowed similarly.\nWhen checking that a value isn&#8217;t <code>null<\/code> or <code>undefined<\/code>, TypeScript now just intersects it with <code>{}<\/code> &#8211; which again, is the same as saying it&#8217;s <code>NonNullable<\/code>.\nPutting many of the changes here together, we can now define the following function without any type assertions.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span style=\"color: #0000FF;\">function<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #795E26;\">throwIfNullable<\/span><span style=\"color: #000000;\">&lt;<\/span><span style=\"color: #267F99;\">T<\/span><span style=\"color: #000000;\">&gt;(<\/span><span style=\"color: #001080;\">value<\/span><span style=\"color: #000000;\">: <\/span><span style=\"color: #267F99;\">T<\/span><span style=\"color: #000000;\">): <\/span><span style=\"color: #267F99;\">NonNullable<\/span><span style=\"color: #000000;\">&lt;<\/span><span style=\"color: #267F99;\">T<\/span><span style=\"color: #000000;\">&gt; {<\/span>\r\n<span style=\"color: #000000;\">    <\/span><span style=\"color: #AF00DB;\">if<\/span><span style=\"color: #000000;\"> (<\/span><span style=\"color: #001080;\">value<\/span><span style=\"color: #000000;\"> === <\/span><span style=\"color: #0000FF;\">undefined<\/span><span style=\"color: #000000;\"> || <\/span><span style=\"color: #001080;\">value<\/span><span style=\"color: #000000;\"> === <\/span><span style=\"color: #0000FF;\">null<\/span><span style=\"color: #000000;\">) {<\/span>\r\n<span style=\"color: #000000;\">        <\/span><span style=\"color: #AF00DB;\">throw<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #795E26;\">Error<\/span><span style=\"color: #000000;\">(<\/span><span style=\"color: #A31515;\">&quot;Nullable value!&quot;<\/span><span style=\"color: #000000;\">);<\/span>\r\n<span style=\"color: #000000;\">    }<\/span>\r\n\r\n<span style=\"color: #000000;\">    <\/span><span style=\"color: #008000;\">\/\/ Used to fail because 'T' was not assignable to 'NonNullable&lt;T&gt;'.<\/span>\r\n<span style=\"color: #000000;\">    <\/span><span style=\"color: #008000;\">\/\/ Now narrows to 'T &amp; {}' and succeeds because that's just 'NonNullable&lt;T&gt;'.<\/span>\r\n<span style=\"color: #000000;\">    <\/span><span style=\"color: #AF00DB;\">return<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #001080;\">value<\/span><span style=\"color: #000000;\">;<\/span>\r\n<span style=\"color: #000000;\">}<\/span>\r\n<\/code><\/pre>\n<p><code>value<\/code> now gets narrowed to <code>T &amp; {}<\/code>, and is now identical with <code>NonNullable&lt;T&gt;<\/code> &#8211; so the body of the function just works with no TypeScript-specific syntax.<\/p>\n<p>On their own, these changes may appear small &#8211; but they represent fixes for many many paper cuts that have been reported over several years.<\/p>\n<p>For more specifics on these improvements, you can <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/49119\">read more here<\/a>.<\/p>\n<h2><a name=\"infer-types-template-strings\"><\/a> Improved Inference for <code>infer<\/code> Types in Template String Types<\/h2>\n<p>TypeScript recently introduced a way to add <code>extends<\/code> constraints to <code>infer<\/code> type variables in conditional types.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span style=\"color: #008000;\">\/\/ Grabs the first element of a tuple if it's assignable to 'number',<\/span>\r\n<span style=\"color: #008000;\">\/\/ and returns 'never' if it can't find one.<\/span>\r\n<span style=\"color: #0000FF;\">type<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #267F99;\">TryGetNumberIfFirst<\/span><span style=\"color: #000000;\">&lt;<\/span><span style=\"color: #267F99;\">T<\/span><span style=\"color: #000000;\">&gt; =<\/span>\r\n<span style=\"color: #000000;\">    <\/span><span style=\"color: #267F99;\">T<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #0000FF;\">extends<\/span><span style=\"color: #000000;\"> [<\/span><span style=\"color: #0000FF;\">infer<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #267F99;\">U<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #0000FF;\">extends<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #267F99;\">number<\/span><span style=\"color: #000000;\">, ...<\/span><span style=\"color: #267F99;\">unknown<\/span><span style=\"color: #000000;\">[]] ? <\/span><span style=\"color: #267F99;\">U<\/span><span style=\"color: #000000;\"> : <\/span><span style=\"color: #267F99;\">never<\/span><span style=\"color: #000000;\">;<\/span>\r\n<\/code><\/pre>\n<p>If these <code>infer<\/code> types appear in a template string type and are constrained to a primitive type, TypeScript will now try to parse out a literal type.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span style=\"color: #008000;\">\/\/ SomeNum used to be 'number'; now it's '100'.<\/span>\r\n<span style=\"color: #0000FF;\">type<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #267F99;\">SomeNum<\/span><span style=\"color: #000000;\"> = <\/span><span style=\"color: #A31515;\">&quot;100&quot;<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #0000FF;\">extends<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #A31515;\">`<\/span><span style=\"color: #0000FF;\">${<\/span><span style=\"color: #0000FF;\">infer<\/span><span style=\"color: #000000FF;\"> <\/span><span style=\"color: #267F99;\">U<\/span><span style=\"color: #000000FF;\"> <\/span><span style=\"color: #0000FF;\">extends<\/span><span style=\"color: #000000FF;\"> <\/span><span style=\"color: #267F99;\">number<\/span><span style=\"color: #0000FF;\">}<\/span><span style=\"color: #A31515;\">`<\/span><span style=\"color: #000000;\"> ? <\/span><span style=\"color: #267F99;\">U<\/span><span style=\"color: #000000;\"> : <\/span><span style=\"color: #267F99;\">never<\/span><span style=\"color: #000000;\">;<\/span>\r\n\r\n<span style=\"color: #008000;\">\/\/ SomeBigInt used to be 'bigint'; now it's '100n'.<\/span>\r\n<span style=\"color: #0000FF;\">type<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #267F99;\">SomeBigInt<\/span><span style=\"color: #000000;\"> = <\/span><span style=\"color: #A31515;\">&quot;100&quot;<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #0000FF;\">extends<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #A31515;\">`<\/span><span style=\"color: #0000FF;\">${<\/span><span style=\"color: #0000FF;\">infer<\/span><span style=\"color: #000000FF;\"> <\/span><span style=\"color: #267F99;\">U<\/span><span style=\"color: #000000FF;\"> <\/span><span style=\"color: #0000FF;\">extends<\/span><span style=\"color: #000000FF;\"> <\/span><span style=\"color: #267F99;\">bigint<\/span><span style=\"color: #0000FF;\">}<\/span><span style=\"color: #A31515;\">`<\/span><span style=\"color: #000000;\"> ? <\/span><span style=\"color: #267F99;\">U<\/span><span style=\"color: #000000;\"> : <\/span><span style=\"color: #267F99;\">never<\/span><span style=\"color: #000000;\">;<\/span>\r\n\r\n<span style=\"color: #008000;\">\/\/ SomeBool used to be 'boolean'; now it's 'true'.<\/span>\r\n<span style=\"color: #0000FF;\">type<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #267F99;\">SomeBool<\/span><span style=\"color: #000000;\"> = <\/span><span style=\"color: #A31515;\">&quot;true&quot;<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #0000FF;\">extends<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #A31515;\">`<\/span><span style=\"color: #0000FF;\">${<\/span><span style=\"color: #0000FF;\">infer<\/span><span style=\"color: #000000FF;\"> <\/span><span style=\"color: #267F99;\">U<\/span><span style=\"color: #000000FF;\"> <\/span><span style=\"color: #0000FF;\">extends<\/span><span style=\"color: #000000FF;\"> <\/span><span style=\"color: #267F99;\">boolean<\/span><span style=\"color: #0000FF;\">}<\/span><span style=\"color: #A31515;\">`<\/span><span style=\"color: #000000;\"> ? <\/span><span style=\"color: #267F99;\">U<\/span><span style=\"color: #000000;\"> : <\/span><span style=\"color: #267F99;\">never<\/span><span style=\"color: #000000;\">;<\/span>\r\n<\/code><\/pre>\n<p>This can now better convey what a library will do at runtime, and give more precise types.<\/p>\n<p>One note on this is that when TypeScript parses these literal types out it will greedily try to parse out as much of what looks like of the appropriate primitive type;\nhowever it then checks to see if the print-back of that primitive matches up with the string contents.\nIn other words, TypeScript checks whether the going from the string, to the primitive, and back matches.\nIf it doesn&#8217;t see that the string can be &quot;round-tripped&quot;, then it will fall back to the base primitive type.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span style=\"color: #008000;\">\/\/ JustNumber is `number` here because TypeScript parses out `&quot;1.0&quot;`, but `String(Number(&quot;1.0&quot;))` is `&quot;1&quot;` and doesn't match.<\/span>\r\n<span style=\"color: #0000FF;\">type<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #267F99;\">JustNumber<\/span><span style=\"color: #000000;\"> = <\/span><span style=\"color: #A31515;\">&quot;1.0&quot;<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #0000FF;\">extends<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #A31515;\">`<\/span><span style=\"color: #0000FF;\">${<\/span><span style=\"color: #0000FF;\">infer<\/span><span style=\"color: #000000FF;\"> <\/span><span style=\"color: #267F99;\">T<\/span><span style=\"color: #000000FF;\"> <\/span><span style=\"color: #0000FF;\">extends<\/span><span style=\"color: #000000FF;\"> <\/span><span style=\"color: #267F99;\">number<\/span><span style=\"color: #0000FF;\">}<\/span><span style=\"color: #A31515;\">`<\/span><span style=\"color: #000000;\"> ? <\/span><span style=\"color: #267F99;\">T<\/span><span style=\"color: #000000;\"> : <\/span><span style=\"color: #267F99;\">never<\/span><span style=\"color: #000000;\">; <\/span>\r\n<\/code><\/pre>\n<p>You can <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/48094\">see more about this feature here<\/a>.<\/p>\n<h2><a name=\"build-watch-incremental-improvements\"><\/a> <code>--build<\/code>, <code>--watch<\/code>, and <code>--incremental<\/code> Performance Improvements<\/h2>\n<p>TypeScript 4.8 introduces several optimizations that should speed up scenarios around <code>--watch<\/code> and <code>--incremental<\/code>, along with project references builds using <code>--build<\/code>.\nFor example, TypeScript is now able to avoid spending time updating timestamps during no-op changes in <code>--watch<\/code> mode, which makes rebuilds faster and avoids messing with other build tools that might be watching for TypeScript&#8217;s output.\nMany other optimizations where we&#8217;re able to reuse information across <code>--build<\/code>, <code>--watch<\/code>, and <code>--incremental<\/code> have been introduced as well.<\/p>\n<p>How big are these improvements?\nWell, on a fairly large internal codebase, we&#8217;ve seen time reductions on the order of 10%-25% on many simple common operations, with around 40% time reductions in no-change scenarios.\nWe&#8217;ve seen similar results on the TypeScript codebase as well.<\/p>\n<p>You can see <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/48784\">the changes, along with the performance results on GitHub<\/a>.<\/p>\n<h2><a name=\"object-array-comparison-errors\"><\/a> Errors When Comparing Object and Array Literals<\/h2>\n<p>In many languages, operators like <code>==<\/code> perform what&#8217;s called &quot;value&quot; equality on objects.\nFor example, in Python it&#8217;s valid to check whether a list is empty by checking whether a value is equal to the empty list using <code>==<\/code>.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span style=\"color: #AF00DB;\">if<\/span><span style=\"color: #000000;\"> people_at_home == []:<\/span>\r\n<span style=\"color: #000000;\">    <\/span><span style=\"color: #795E26;\">print<\/span><span style=\"color: #000000;\">(<\/span><span style=\"color: #A31515;\">&quot;that's where she lies, broken inside. &lt;\/3&quot;<\/span><span style=\"color: #000000;\">)<\/span>\r\n<\/code><\/pre>\n<p>This is not the case in JavaScript, where <code>==<\/code> and <code>===<\/code> between objects and arrays check whether both references point to the same instance.\nWe believe that this is at best an early foot-gun for JavaScript developers, and at worst a bug in production code.\nThat&#8217;s why TypeScript now disallows code like the following.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span style=\"color: #0000FF;\">let<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #001080;\">peopleAtHome<\/span><span style=\"color: #000000;\"> = [];<\/span>\r\n\r\n<span style=\"color: #AF00DB;\">if<\/span><span style=\"color: #000000;\"> (<\/span><span style=\"color: #001080;\">peopleAtHome<\/span><span style=\"color: #000000;\"> === []) {<\/span>\r\n<span style=\"color: #008000;\">\/\/  ~~~~~~~~~~~~~~~~~~~<\/span>\r\n<span style=\"color: #008000;\">\/\/ This condition will always return 'false' since JavaScript compares objects by reference, not value.<\/span>\r\n<span style=\"color: #000000;\">    <\/span><span style=\"color: #001080;\">console<\/span><span style=\"color: #000000;\">.<\/span><span style=\"color: #795E26;\">log<\/span><span style=\"color: #000000;\">(<\/span><span style=\"color: #A31515;\">&quot;that's where she lies, broken inside. &lt;\/3&quot;<\/span><span style=\"color: #000000;\">)<\/span>\r\n<span style=\"color: #000000;\">}<\/span>\r\n<\/code><\/pre>\n<p>We&#8217;d like to extend our gratitude to <a href=\"https:\/\/github.com\/Jack-Works\">Jack Works<\/a> who contributed this check.\nYou can <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/45978\">view the changes involved here<\/a>.<\/p>\n<h2><a name=\"inference-binding-patterns\"><\/a> Improved Inference from Binding Patterns<\/h2>\n<p>In some cases, TypeScript will pick up a type from a binding pattern to make better inferences.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span style=\"color: #0000FF;\">declare<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #0000FF;\">function<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #795E26;\">chooseRandomly<\/span><span style=\"color: #000000;\">&lt;<\/span><span style=\"color: #267F99;\">T<\/span><span style=\"color: #000000;\">&gt;(<\/span><span style=\"color: #001080;\">x<\/span><span style=\"color: #000000;\">: <\/span><span style=\"color: #267F99;\">T<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #001080;\">y<\/span><span style=\"color: #000000;\">: <\/span><span style=\"color: #267F99;\">T<\/span><span style=\"color: #000000;\">): <\/span><span style=\"color: #267F99;\">T<\/span><span style=\"color: #000000;\">;<\/span>\r\n\r\n<span style=\"color: #0000FF;\">let<\/span><span style=\"color: #000000;\"> [<\/span><span style=\"color: #001080;\">a<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #001080;\">b<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #001080;\">c<\/span><span style=\"color: #000000;\">] = <\/span><span style=\"color: #795E26;\">chooseRandomly<\/span><span style=\"color: #000000;\">([<\/span><span style=\"color: #098658;\">42<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #0000FF;\">true<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #A31515;\">&quot;hi!&quot;<\/span><span style=\"color: #000000;\">], [<\/span><span style=\"color: #098658;\">0<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #0000FF;\">false<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #A31515;\">&quot;bye!&quot;<\/span><span style=\"color: #000000;\">]);<\/span>\r\n<span style=\"color: #008000;\">\/\/   ^  ^  ^<\/span>\r\n<span style=\"color: #008000;\">\/\/   |  |  |<\/span>\r\n<span style=\"color: #008000;\">\/\/   |  |  string<\/span>\r\n<span style=\"color: #008000;\">\/\/   |  |<\/span>\r\n<span style=\"color: #008000;\">\/\/   |  boolean<\/span>\r\n<span style=\"color: #008000;\">\/\/   |<\/span>\r\n<span style=\"color: #008000;\">\/\/   number<\/span>\r\n<\/code><\/pre>\n<p>When <code>chooseRandomly<\/code> needs to figure out a type for <code>T<\/code>, it will primarily look at <code>[42, true, &quot;hi!&quot;]<\/code> and <code>[0, false, &quot;bye!&quot;]<\/code>;\nbut TypeScript needs to figure out whether those two types should be <code>Array&lt;number | boolean | string&gt;<\/code> or the tuple type <code>[number, boolean, string]<\/code>.\nTo do that, it will look for existing candidates as a hint to see whether there are any tuple types.\nWhen TypeScript sees the binding pattern <code>[a, b, c]<\/code>, it creates the type <code>[any, any, any]<\/code>, and that type gets picked up as a low-priority candidate for <code>T<\/code> which also gets used as a hint for the types of <code>[42, true, &quot;hi!&quot;]<\/code> and <code>[0, false, &quot;bye!&quot;]<\/code>.<\/p>\n<p>You can see how this was good for <code>chooseRandomly<\/code>, but it fell short in other cases.\nFor example, take the following code<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span style=\"color: #0000FF;\">declare<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #0000FF;\">function<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #795E26;\">f<\/span><span style=\"color: #000000;\">&lt;<\/span><span style=\"color: #267F99;\">T<\/span><span style=\"color: #000000;\">&gt;(<\/span><span style=\"color: #001080;\">x<\/span><span style=\"color: #000000;\">?: <\/span><span style=\"color: #267F99;\">T<\/span><span style=\"color: #000000;\">): <\/span><span style=\"color: #267F99;\">T<\/span><span style=\"color: #000000;\">;<\/span>\r\n\r\n<span style=\"color: #0000FF;\">let<\/span><span style=\"color: #000000;\"> [<\/span><span style=\"color: #001080;\">x<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #001080;\">y<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #001080;\">z<\/span><span style=\"color: #000000;\">] = <\/span><span style=\"color: #795E26;\">f<\/span><span style=\"color: #000000;\">();<\/span>\r\n<\/code><\/pre>\n<p>The binding pattern <code>[x, y, z]<\/code> hinted that <code>f<\/code> should produce an <code>[any, any, any]<\/code> tuple;\nbut <code>f<\/code> really shouldn&#8217;t change its type argument based on a binding pattern.\nIt can&#8217;t suddenly conjure up a new array-like value based on what it&#8217;s being assigned to, so the binding pattern type has way too much influence on the produced type.\nOn top of that, because the binding pattern type is full of <code>any<\/code>s, we&#8217;re left with <code>x<\/code>, <code>y<\/code>, and <code>z<\/code> being typed as <code>any<\/code>.<\/p>\n<p>In TypeScript 4.8, these binding patterns are never used as candidates for type arguments.\nInstead, they&#8217;re just consulted in case a parameter needs a more specific type like in our <code>chooseRandomly<\/code> example.\nIf you need to revert to the old behavior, you can always provide explicit type arguments.<\/p>\n<p>You can <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/49086\">look at the change on GitHub<\/a> if you&#8217;re curious to learn more.<\/p>\n<h2><a name=\"file-watching-fixes\"><\/a> File-Watching Fixes (Especially Across <code>git checkout<\/code>s)<\/h2>\n<p>We&#8217;ve had a long-standing bug where TypeScript has a very hard time with certain file changes in <code>--watch<\/code> mode and editor scenarios.\nSometimes the symptoms are stale or inaccurate errors that might show up that require restarting <code>tsc<\/code> or VS Code.\nFrequently these occur on Unix systems, and you might have seen these after saving a file with vim or swapping branches in git.<\/p>\n<p>This was caused by assumptions of how Node.js handles rename events across file systems.\nFile systems used by Linux and macOS utilize <a href=\"https:\/\/en.wikipedia.org\/wiki\/Inode\">inodes<\/a>, and <a href=\"https:\/\/nodejs.org\/api\/fs.html#inodes\">Node.js will attach file watchers to inodes rather than file paths<\/a>.\nSo when Node.js returns <a href=\"https:\/\/nodejs.org\/api\/fs.html#class-fsfswatcher\">a watcher object<\/a>, it might be watching a path or an inode depending on the platform and file system.<\/p>\n<p>To be a bit more efficient, TypeScript tries to reuse the same watcher objects if it detects a path still exists on disk.\nThis is where things went wrong, because even if a file still exists at that path, a distinct file might have been created, and that file will have a different inode.\nSo TypeScript would end up reusing the watcher object instead of installing a new watcher at the original location, and watch for changes at what might be a totally irrelevant file.\nSo TypeScript 4.8 now handles these cases on inode systems and properly installs a new watcher and fixes this.<\/p>\n<p>We&#8217;d like to extend our thanks to <a href=\"https:\/\/github.com\/MarcCelani-at\">Marc Celani<\/a> and his team at Airtable who invested lots of time in investigating the issues they were experiencing and pointing out the root cause.\nYou can view <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/48997\">the specific fixes around file-watching here<\/a>.<\/p>\n<h2><a name=\"find-all-refs-improvements\"><\/a> Find-All-References Performance Improvements<\/h2>\n<p>When running find-all-references in your editor, TypeScript is now able to act a little smarter as it aggregates references.\nThis reduced the amount of time TypeScript took to search a widely-used identifier in its own codebase by about 20%.<\/p>\n<p><a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/49581\">You can read up more on the improvement here<\/a>.<\/p>\n<h2><a name=\"exclude-globs-auto-import\"><\/a> Exclude Specific Files from Auto-Imports<\/h2>\n<p>TypeScript 4.8 introduces an editor preference for excluding files from auto-imports.\nIn Visual Studio Code, file names or globs can be added under &quot;Auto Import File Exclude Patterns&quot; in the Settings UI, or in a <code>.vscode\/settings.json<\/code> file:<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span style=\"color: #000000;\">{<\/span>\r\n<span style=\"color: #000000;\">    <\/span><span style=\"color: #008000;\">\/\/ Note that `javascript.preferences.autoImportFileExcludePatterns` can be specified for JavaScript too.<\/span>\r\n<span style=\"color: #000000;\">    <\/span><span style=\"color: #0451A5;\">&quot;typescript.preferences.autoImportFileExcludePatterns&quot;<\/span><span style=\"color: #000000;\">: [<\/span>\r\n<span style=\"color: #000000;\">      <\/span><span style=\"color: #A31515;\">&quot;**\/node_modules\/@types\/node&quot;<\/span>\r\n<span style=\"color: #000000;\">    ]<\/span>\r\n<span style=\"color: #000000;\">}<\/span>\r\n<\/code><\/pre>\n<p>This can be useful in cases where you can&#8217;t avoid having certain modules or libraries in your compilation but you rarely want to import from them.\nThese modules might have lots of exports that can pollute the auto-imports list and make it harder to navigate, and this option can help in those situations.<\/p>\n<p>You can <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/49578\">see more specifics about the implementation here<\/a>.<\/p>\n<h2><a name=\"correctness-changes\"><\/a> Correctness Fixes and Breaking Changes<\/h2>\n<p>Due to the nature of type system changes, there are very few changes that can be made that don&#8217;t affect <em>some<\/em> code;\nhowever, there are a few changes that are more likely to require adapting existing code.<\/p>\n<h3><code>lib.d.ts<\/code> Updates<\/h3>\n<p>While TypeScript strives to avoid major breaks, even small changes in the built-in libraries can cause issues.\nWe don&#8217;t expect major breaks as a result of DOM and <code>lib.d.ts<\/code> updates, but one notable change is that the <code>cause<\/code> property on <code>Error<\/code>s now has the type <code>unknown<\/code> instead of <code>Error<\/code>.<\/p>\n<h3>Unconstrained Generics No Longer Assignable to <code>{}<\/code><\/h3>\n<p>In TypeScript 4.8, for projects with <code>strictNullChecks<\/code> enabled, TypeScript will now correctly issue an error when an unconstrained type parameter is used in a position where <code>null<\/code> or <code>undefined<\/code> are not legal values.\nThat will include any type that expects <code>{}<\/code>, <code>object<\/code>, or an object type with all-optional properties.<\/p>\n<p>A simple example can be seen in the following.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span style=\"color: #008000;\">\/\/ Accepts any non-null non-undefined value<\/span>\r\n<span style=\"color: #0000FF;\">function<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #795E26;\">bar<\/span><span style=\"color: #000000;\">(<\/span><span style=\"color: #001080;\">value<\/span><span style=\"color: #000000;\">: {}) {<\/span>\r\n<span style=\"color: #000000;\">  <\/span><span style=\"color: #001080;\">Object<\/span><span style=\"color: #000000;\">.<\/span><span style=\"color: #795E26;\">keys<\/span><span style=\"color: #000000;\">(<\/span><span style=\"color: #001080;\">value<\/span><span style=\"color: #000000;\">); <\/span><span style=\"color: #008000;\">\/\/ This call throws on null\/undefined at runtime.<\/span>\r\n<span style=\"color: #000000;\">}<\/span>\r\n\r\n<span style=\"color: #008000;\">\/\/ Unconstrained type parameter T...<\/span>\r\n<span style=\"color: #0000FF;\">function<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #795E26;\">foo<\/span><span style=\"color: #000000;\">&lt;<\/span><span style=\"color: #267F99;\">T<\/span><span style=\"color: #000000;\">&gt;(<\/span><span style=\"color: #001080;\">x<\/span><span style=\"color: #000000;\">: <\/span><span style=\"color: #267F99;\">T<\/span><span style=\"color: #000000;\">) {<\/span>\r\n<span style=\"color: #000000;\">    <\/span><span style=\"color: #795E26;\">bar<\/span><span style=\"color: #000000;\">(<\/span><span style=\"color: #001080;\">x<\/span><span style=\"color: #000000;\">); <\/span><span style=\"color: #008000;\">\/\/ Used to be allowed, now is an error in 4.8.<\/span>\r\n<span style=\"color: #000000;\">    <\/span><span style=\"color: #008000;\">\/\/  ~<\/span>\r\n<span style=\"color: #000000;\">    <\/span><span style=\"color: #008000;\">\/\/ error: Argument of type 'T' is not assignable to parameter of type '{}'.<\/span>\r\n<span style=\"color: #000000;\">}<\/span>\r\n\r\n<span style=\"color: #795E26;\">foo<\/span><span style=\"color: #000000;\">(<\/span><span style=\"color: #0000FF;\">undefined<\/span><span style=\"color: #000000;\">);<\/span>\r\n<\/code><\/pre>\n<p>As demonstrated above, code like this has a potential bug &#8211; the values <code>null<\/code> and <code>undefined<\/code> can be indirectly passed through these unconstrained type parameters to code that is not supposed to observe those values.<\/p>\n<p>This behavior will also be visible in type positions. One example would be:<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span style=\"color: #0000FF;\">interface<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #267F99;\">Foo<\/span><span style=\"color: #000000;\">&lt;<\/span><span style=\"color: #267F99;\">T<\/span><span style=\"color: #000000;\">&gt; {<\/span>\r\n<span style=\"color: #000000;\">  <\/span><span style=\"color: #001080;\">x<\/span><span style=\"color: #000000;\">: <\/span><span style=\"color: #267F99;\">Bar<\/span><span style=\"color: #000000;\">&lt;<\/span><span style=\"color: #267F99;\">T<\/span><span style=\"color: #000000;\">&gt;;<\/span>\r\n<span style=\"color: #000000;\">}<\/span>\r\n\r\n<span style=\"color: #0000FF;\">interface<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #267F99;\">Bar<\/span><span style=\"color: #000000;\">&lt;<\/span><span style=\"color: #267F99;\">T<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #0000FF;\">extends<\/span><span style=\"color: #000000;\"> {}&gt; { }<\/span>\r\n<\/code><\/pre>\n<p>Existing code that didn&#8217;t want to handle <code>null<\/code> and <code>undefined<\/code> can be fixed by propagating the appropriate constraints through.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span style=\"color: #A31515;\">- function foo&lt;T&gt;(x: T) {<\/span>\r\n<span style=\"color: #098658;\">+ function foo&lt;T extends {}&gt;(x: T) {<\/span>\r\n<\/code><\/pre>\n<p>Another work-around would be to check for <code>null<\/code> and <code>undefined<\/code> at runtime.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span style=\"color: #000000;\">  function foo&lt;T&gt;(x: T) {<\/span>\r\n<span style=\"color: #098658;\">+     if (x !== null &amp;&amp; x !== undefined) {<\/span>\r\n<span style=\"color: #000000;\">          bar(x);<\/span>\r\n<span style=\"color: #098658;\">+     }<\/span>\r\n<span style=\"color: #000000;\">  }<\/span>\r\n<\/code><\/pre>\n<p>And if you know that for some reason, your generic value can&#8217;t be <code>null<\/code> or <code>undefined<\/code>, you can just use a non-null assertion.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span style=\"color: #000000;\">  function foo&lt;T&gt;(x: T) {<\/span>\r\n<span style=\"color: #A31515;\">-     bar(x);<\/span>\r\n<span style=\"color: #098658;\">+     bar(x!);<\/span>\r\n<span style=\"color: #000000;\">  }<\/span>\r\n<\/code><\/pre>\n<p>When it comes to types, you&#8217;ll often either need to propagate constraints, or intersect your types with <code>{}<\/code>.<\/p>\n<p>For more information, you can <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/49119\">see the change that introduced this<\/a> along with <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/issues\/49489\">the specific discussion issue regarding how unconstrained generics now work<\/a>.<\/p>\n<h3>Types Cannot Be Imported\/Exported in JavaScript Files<\/h3>\n<p>TypeScript previously allowed JavaScript files to import and export entities declared with a type, but no value, in <code>import<\/code> and <code>export<\/code> statements.\nThis behavior was incorrect, because named imports and exports for values that don&#8217;t exist will cause a runtime error under ECMAScript modules.\nWhen a JavaScript file is type-checked under <code>--checkJs<\/code> or through a <code>\/\/ @ts-check<\/code> comment, TypeScript will now issue an error.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span style=\"color: #008000;\">\/\/ @ts-check<\/span>\r\n\r\n<span style=\"color: #008000;\">\/\/ Will fail at runtime because 'SomeType' is not a value.<\/span>\r\n<span style=\"color: #AF00DB;\">import<\/span><span style=\"color: #000000;\"> { <\/span><span style=\"color: #001080;\">someValue<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #001080;\">SomeType<\/span><span style=\"color: #000000;\"> } <\/span><span style=\"color: #AF00DB;\">from<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #A31515;\">&quot;some-module&quot;<\/span><span style=\"color: #000000;\">;<\/span>\r\n\r\n<span style=\"color: #008000;\">\/**<\/span>\r\n<span style=\"color: #008000;\"> * <\/span><span style=\"color: #0000FF;\">@type<\/span><span style=\"color: #008000;\"> <\/span><span style=\"color: #267F99;\">{SomeType}<\/span>\r\n<span style=\"color: #008000;\"> *\/<\/span>\r\n<span style=\"color: #AF00DB;\">export<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #0000FF;\">const<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #0070C1;\">myValue<\/span><span style=\"color: #000000;\"> = <\/span><span style=\"color: #001080;\">someValue<\/span><span style=\"color: #000000;\">;<\/span>\r\n\r\n<span style=\"color: #008000;\">\/**<\/span>\r\n<span style=\"color: #008000;\"> * <\/span><span style=\"color: #0000FF;\">@typedef<\/span><span style=\"color: #008000;\"> <\/span><span style=\"color: #267F99;\">{string | number}<\/span><span style=\"color: #008000;\"> <\/span><span style=\"color: #267F99;\">MyType<\/span>\r\n<span style=\"color: #008000;\"> *\/<\/span>\r\n\r\n<span style=\"color: #008000;\">\/\/ Will fail at runtime because 'MyType' is not a value.<\/span>\r\n<span style=\"color: #AF00DB;\">export<\/span><span style=\"color: #000000;\"> { <\/span><span style=\"color: #001080;\">MyType<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #AF00DB;\">as<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #001080;\">MyExportedType<\/span><span style=\"color: #000000;\"> };<\/span>\r\n<\/code><\/pre>\n<p>To reference a type from another module, you can instead directly qualify the import.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span style=\"color: #A31515;\">- import { someValue, SomeType } from &quot;some-module&quot;;<\/span>\r\n<span style=\"color: #098658;\">+ import { someValue } from &quot;some-module&quot;;<\/span>\r\n<span style=\"color: #000000;\">  <\/span>\r\n<span style=\"color: #000000;\">  \/**<\/span>\r\n<span style=\"color: #A31515;\">-  * @type {SomeType}<\/span>\r\n<span style=\"color: #098658;\">+  * @type {import(&quot;some-module&quot;).SomeType}<\/span>\r\n<span style=\"color: #000000;\">   *\/<\/span>\r\n<span style=\"color: #000000;\">  export const myValue = someValue;<\/span>\r\n<\/code><\/pre>\n<p>To export a type, you can just use a <code>\/** @typedef *\/<\/code> comment in JSDoc.\n<code>@typedef<\/code> comments already automatically export types from their containing modules.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span style=\"color: #000000;\">  \/**<\/span>\r\n<span style=\"color: #000000;\">   * @typedef {string | number} MyType<\/span>\r\n<span style=\"color: #000000;\">   *\/<\/span>\r\n\r\n<span style=\"color: #098658;\">+ \/**<\/span>\r\n<span style=\"color: #098658;\">+  * @typedef {MyType} MyExportedType<\/span>\r\n<span style=\"color: #098658;\">+  *\/<\/span>\r\n<span style=\"color: #A31515;\">- export { MyType as MyExportedType };<\/span>\r\n<\/code><\/pre>\n<p>You can <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/49580\">read more about the change here<\/a>.<\/p>\n<h3>Binding Patterns Do Not Directly Contribute to Inference Candidates<\/h3>\n<p>As mentioned above, binding patterns no longer change the type of inference results in function calls.\nYou can <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/49086\">read more about the original change here<\/a>.<\/p>\n<h3>Unused Renames in Binding Patterns are Now Errors in Type Signatures<\/h3>\n<p>TypeScript&#8217;s type annotation syntax often looks like it can be used when destructuring values.\nFor example, take the following function.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span style=\"color: #0000FF;\">declare<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #0000FF;\">function<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #795E26;\">makeCar<\/span><span style=\"color: #000000;\">({ <\/span><span style=\"color: #001080;\">name<\/span><span style=\"color: #000000;\">: <\/span><span style=\"color: #001080;\">string<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #001080;\">age<\/span><span style=\"color: #000000;\">: <\/span><span style=\"color: #001080;\">number<\/span><span style=\"color: #000000;\"> }): <\/span><span style=\"color: #267F99;\">Person<\/span><span style=\"color: #000000;\">;<\/span>\r\n<\/code><\/pre>\n<p>You might read this signature and thing that <code>makePerson<\/code> obviously takes an object with a <code>name<\/code> property with the type <code>string<\/code> and an <code>age<\/code> property with the type <code>number<\/code>;\nhowever, JavaScript&#8217;s destructuring syntax is actually taking precedence here.\n<code>makePerson<\/code> does say that it&#8217;s going to take an object with a <code>name<\/code> and an <code>age<\/code> property, but instead of specifying a type for them, it&#8217;s just saying that it renames <code>name<\/code> and <code>age<\/code> to <code>string<\/code> and <code>number<\/code> respectively.<\/p>\n<p>In a pure type construct, writing code like this is useless, and typically a mistake since developers usually assume they&#8217;re writing a type annotation.<\/p>\n<p>TypeScript 4.8 makes these an error unless they&#8217;re referenced later in the signature.\nThe correct way to write the above signature would be as follows:<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span style=\"color: #0000FF;\">declare<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #0000FF;\">function<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #795E26;\">makePerson<\/span><span style=\"color: #000000;\">(<\/span><span style=\"color: #001080;\">options<\/span><span style=\"color: #000000;\">: { <\/span><span style=\"color: #001080;\">name<\/span><span style=\"color: #000000;\">: <\/span><span style=\"color: #267F99;\">string<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #001080;\">age<\/span><span style=\"color: #000000;\">: <\/span><span style=\"color: #267F99;\">number<\/span><span style=\"color: #000000;\"> }): <\/span><span style=\"color: #267F99;\">Person<\/span><span style=\"color: #000000;\">;<\/span>\r\n\r\n<span style=\"color: #008000;\">\/\/ or<\/span>\r\n\r\n<span style=\"color: #0000FF;\">declare<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #0000FF;\">function<\/span><span style=\"color: #000000;\"> <\/span><span style=\"color: #795E26;\">makePerson<\/span><span style=\"color: #000000;\">({ <\/span><span style=\"color: #001080;\">name<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #001080;\">age<\/span><span style=\"color: #000000;\"> }: { <\/span><span style=\"color: #001080;\">name<\/span><span style=\"color: #000000;\">: <\/span><span style=\"color: #267F99;\">string<\/span><span style=\"color: #000000;\">, <\/span><span style=\"color: #001080;\">age<\/span><span style=\"color: #000000;\">: <\/span><span style=\"color: #267F99;\">number<\/span><span style=\"color: #000000;\"> }): <\/span><span style=\"color: #267F99;\">Person<\/span><span style=\"color: #000000;\">;<\/span>\r\n<\/code><\/pre>\n<p>This change can catch bugs in declarations, and has been helpful for improving existing code.\nWe&#8217;d like to extend our thanks to <a href=\"https:\/\/github.com\/uhyo\">GitHub user uhyo<\/a> for providing this check.\n<a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/41044\">You can read up on the change here<\/a>.<\/p>\n<h2>What&#8217;s Next?<\/h2>\n<p>In the coming weeks, our team will be focusing on work for TypeScript 4.9, while only making critical fixes for TypeScript 4.8&#8217;s stable release.\nYou can keep track of our target dates on the <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/issues\/49074\">TypeScript 4.8 Iteration Plan<\/a>.<\/p>\n<p>In the meantime, download the Release Candidate today, and if you run into anything, <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/issues\">give us your feedback<\/a> so we can make TypeScript 4.8 even better!<\/p>\n<p>Happy Hacking!<\/p>\n<p>&#8211; Daniel Rosenwasser and the TypeScript Team<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today we&#8217;re excited to announce our Release Candidate (RC) of TypeScript 4.8. Between now and the stable release of TypeScript 4.8, we expect no further changes apart from critical bug fixes. To get started using the RC, you can get it through NuGet, or use npm with the following command: npm install -D typescript@rc You [&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-3513","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-typescript"],"acf":[],"blog_post_summary":"<p>Today we&#8217;re excited to announce our Release Candidate (RC) of TypeScript 4.8. Between now and the stable release of TypeScript 4.8, we expect no further changes apart from critical bug fixes. To get started using the RC, you can get it through NuGet, or use npm with the following command: npm install -D typescript@rc You [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/3513","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=3513"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/3513\/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=3513"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/categories?post=3513"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/tags?post=3513"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}