{"id":4381,"date":"2024-07-26T06:11:05","date_gmt":"2024-07-26T14:11:05","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/typescript\/?p=4381"},"modified":"2024-07-29T12:44:31","modified_gmt":"2024-07-29T20:44:31","slug":"announcing-typescript-5-6-beta","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-5-6-beta\/","title":{"rendered":"Announcing TypeScript 5.6 Beta"},"content":{"rendered":"<p>Today we are excited to announce the availability of TypeScript 5.6 Beta.<\/p>\n<p>To get started using the beta, you can get it <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.TypeScript.MSBuild\">through NuGet<\/a>, or through npm with the following command:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>npm install -D typescript@beta\r\n<\/code><\/pre>\n<p>Here&#8217;s a quick list of what&#8217;s new in TypeScript 5.6!<\/p>\n<ul>\n<li><a href=\"#disallowed-nullish-and-truthy-checks\">Disallowed Nullish and Truthy Checks<\/a><\/li>\n<li><a href=\"#iterator-helper-methods\">Iterator Helper Methods<\/a><\/li>\n<li><a href=\"#strict-builtin-iterator-checks-and---strictbuiltiniteratorreturn\">Strict Builtin Iterator Checks (and <code>--strictBuiltinIteratorReturn<\/code>)<\/a><\/li>\n<li><a href=\"#support-for-arbitrary-module-identifiers\">Support for Arbitrary Module Identifiers<\/a><\/li>\n<li><a href=\"#the---nouncheckedsideeffectimports-option\">The <code>--noUncheckedSideEffectImports<\/code> Option<\/a><\/li>\n<li><a href=\"#the---nocheck-option\">The <code>--noCheck<\/code> Option<\/a><\/li>\n<li><a href=\"#allow---build-with-intermediate-errors\">Allow <code>--build<\/code> with Intermediate Errors<\/a><\/li>\n<li><a href=\"#region-prioritized-diagnostics-in-editors\">Region-Prioritized Diagnostics in Editors<\/a><\/li>\n<li><a href=\"#search-ancestor-configuration-files-for-project-ownership\">Search Ancestor Configuration Files for Project Ownership<\/a><\/li>\n<li><a href=\"#notable-behavioral-changes\">Notable Behavioral Changes<\/a>\n<ul>\n<li><a href=\"#libdts\"><code>lib.d.ts<\/code><\/a><\/li>\n<li><a href=\"#tsbuildinfo-is-always-written\"><code>.tsbuildinfo<\/code> is Always Written<\/a><\/li>\n<li><a href=\"#respecting-file-extensions-and-packagejson-from-within-node_modules\">Respecting File Extensions and <code>package.json<\/code> from within <code>node_modules<\/code><\/a><\/li>\n<li><a href=\"#correct-override-checks-on-computed-properties\">Correct <code>override<\/code> Checks on Computed Properties<\/a><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h2 id=\"disallowed-nullish-and-truthy-checks\">Disallowed Nullish and Truthy Checks<\/h2>\n<p>Maybe you&#8217;ve written a regex and forgotten to call <code>.test(...)<\/code> on it:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>if (\/0x[0-9a-f]\/) {\r\n    \/\/ Oops! This block always runs.\r\n    \/\/ ...\r\n}\r\n<\/code><\/pre>\n<p>or maybe you&#8217;ve accidentally written <code>=&gt;<\/code> (which creates an arrow function) instead of <code>&gt;=<\/code> (the greater-than-or-equal-to operator):<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>if (x =&gt; 0) {\r\n    \/\/ Oops! This block always runs.\r\n    \/\/ ...\r\n}\r\n<\/code><\/pre>\n<p>or maybe you&#8217;ve tried to use a default value with <code>??<\/code>, but mixed up the precedence of <code>??<\/code> and a comparison operator like <code>&lt;<\/code>:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>function isValid(value: string | number, options: any, strictness: &quot;strict&quot; | &quot;loose&quot;) {\r\n    if (strictness === &quot;loose&quot;) {\r\n        value = +value\r\n    }\r\n    return value &lt; options.max ?? 100;\r\n    \/\/ Oops! This is parsed as (value &lt; options.max) ?? 100\r\n}\r\n\r\n<\/code><\/pre>\n<p>or maybe you&#8217;ve misplaced a parenthesis in a complex expression:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>if (\r\n    isValid(primaryValue, &quot;strict&quot;) || isValid(secondaryValue, &quot;strict&quot;) ||\r\n    isValid(primaryValue, &quot;loose&quot; || isValid(secondaryValue, &quot;loose&quot;))\r\n) {\r\n    \/\/                           ^^^^ \ud83d\udc40 Did we forget a closing ')'?\r\n}\r\n<\/code><\/pre>\n<p>None of these examples do what the author intended, but they&#8217;re all valid JavaScript code.\nPreviously TypeScript also quietly accepted these examples.<\/p>\n<p>But with a little bit of experimentation, we found that many <em>many<\/em> bugs could be caught from flagging down suspicious examples like above.\nIn TypeScript 5.6, the compiler now errors when it can syntactically determine a truthy or nullish check will always evaluate in a specific way.\nSo in the above examples, you&#8217;ll start to see errors:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>if (\/0x[0-9a-f]\/) {\r\n\/\/  ~~~~~~~~~~~~\r\n\/\/ error: This kind of expression is always truthy.\r\n}\r\n\r\nif (x =&gt; 0) {\r\n\/\/  ~~~~~~\r\n\/\/ error: This kind of expression is always truthy.\r\n}\r\n\r\nfunction isValid(value: string | number, options: any, strictness: &quot;strict&quot; | &quot;loose&quot;) {\r\n    if (strictness === &quot;loose&quot;) {\r\n        value = +value\r\n    }\r\n    return value &lt; options.max ?? 100;\r\n    \/\/     ~~~~~~~~~~~~~~~~~~~\r\n    \/\/ error: Right operand of ?? is unreachable because the left operand is never nullish.\r\n}\r\n\r\nif (\r\n    isValid(primaryValue, &quot;strict&quot;) || isValid(secondaryValue, &quot;strict&quot;) ||\r\n    isValid(primaryValue, &quot;loose&quot; || isValid(secondaryValue, &quot;loose&quot;))\r\n) {\r\n    \/\/                    ~~~~~~~\r\n    \/\/ error: This kind of expression is always truthy.\r\n}\r\n<\/code><\/pre>\n<p>Similar results can be achieved by enabling the ESLint <code>no-constant-binary-expression<\/code> rule, and you can <a href=\"https:\/\/eslint.org\/blog\/2022\/07\/interesting-bugs-caught-by-no-constant-binary-expression\/\">see some of the results they achieved in their blog post<\/a>;\nbut the new checks TypeScript performs does not have perfect overlap with the ESLint rule, and we also believe there is a lot of value in having these checks built into TypeScript itself.<\/p>\n<p>Note that certain expressions are still allowed, even if they are always truthy or nullish.\nSpecifically, <code>true<\/code>, <code>false<\/code>, <code>0<\/code>, and <code>1<\/code> are all still allowed despite always being truthy or falsy, since code like the following:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>while (true) {\r\n    doStuff();\r\n\r\n    if (something()) {\r\n        break;\r\n    }\r\n\r\n    doOtherStuff();\r\n}\r\n<\/code><\/pre>\n<p>is still idiomatic and useful, and code like the following:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>if (true || inDebuggingOrDevelopmentEnvironment()) {\r\n    \/\/ ...\r\n}\r\n<\/code><\/pre>\n<p>is useful while iterating\/debugging code.<\/p>\n<p>If you&#8217;re curious about the implementation or the sorts of bugs it catches, take a look at <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/59217\">the pull request that implemented this feature<\/a>.<\/p>\n<h2 id=\"iterator-helper-methods\">Iterator Helper Methods<\/h2>\n<p>JavaScript has a notion of <em>iterables<\/em> (things which we can iterate over by calling a <code>[Symbol.iterator]()<\/code> and getting an iterator) and <em>iterators<\/em> (things which have a <code>next()<\/code> method which we can call to try to get the next value as we iterate).\nBy and large, you don&#8217;t typically have to think about these things when you toss them into a <code>for<\/code>\/<code>of<\/code> loop, or <code>[...spread]<\/code> them into a new array.\nBut TypeScript does model these with the types <code>Iterable<\/code> and <code>Iterator<\/code> (and even <code>IterableIterator<\/code> which acts as both!), and these types describe the minimal set of members you need for constructs like <code>for<\/code>\/<code>of<\/code> to work on them.<\/p>\n<p><code>Iterable<\/code>s (and <code>IterableIterator<\/code>s) are nice because they can be used in all sorts of places in JavaScript &#8211; but a lot of people found themselves missing methods on <code>Array<\/code>s like <code>map<\/code>, <code>filter<\/code>, and for some reason <code>reduce<\/code>.\nThat&#8217;s why <a href=\"https:\/\/github.com\/tc39\/proposal-iterator-helpers\">a recent proposal was brought forward in ECMAScript<\/a> to add many methods (and more) from <code>Array<\/code> onto most of the <code>IterableIterator<\/code>s that are produced in JavaScript.<\/p>\n<p>For example, every generator now produces an object that also has a <code>map<\/code> method and a <code>take<\/code> method.<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>function* positiveIntegers() {\r\n    let i = 1;\r\n    while (true) {\r\n        yield i;\r\n        i++;\r\n    }\r\n}\r\n\r\nconst evenNumbers = positiveIntegers().map(x =&gt; x * 2);\r\n\r\n\/\/ Output:\r\n\/\/    2\r\n\/\/    4\r\n\/\/    6\r\n\/\/    8\r\n\/\/   10\r\nfor (const value of evenNumbers.take(5)) {\r\n    console.log(value);\r\n}\r\n<\/code><\/pre>\n<p>The same is true for methods like <code>keys()<\/code>, <code>values()<\/code>, and <code>entries()<\/code> on <code>Map<\/code>s and <code>Set<\/code>s.<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>function invertKeysAndValues&lt;K, V&gt;(map: Map&lt;K, V&gt;): Map&lt;V, K&gt; {\r\n    return new Map(\r\n        map.entries().map(([k, v]) =&gt; [v, k])\r\n    );\r\n}\r\n<\/code><\/pre>\n<p>You can also extend the new <code>Iterator<\/code> object:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>\/**\r\n * Provides an endless stream of `0`s.\r\n *\/\r\nclass Zeroes extends Iterator&lt;number&gt; {\r\n    next() {\r\n        return { value: 0, done: false } as const;\r\n    }\r\n}\r\n\r\nconst zeroes = new Zeroes();\r\n\r\n\/\/ Transform into an endless stream of `1`s.\r\nconst ones = zeroes.map(x =&gt; x + 1);\r\n<\/code><\/pre>\n<p>And you can adapt any existing <code>Iterable<\/code>s or <code>Iterator<\/code>s into this new type with <code>Iterator.from<\/code>:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>Iterator.from(...).filter(someFunction);\r\n<\/code><\/pre>\n<p>Now, we have to talk about naming.<\/p>\n<p>Earlier we mentioned that TypeScript has types for <code>Iterable<\/code> and <code>Iterator<\/code>;\nhowever, like we mentioned, these act sort of like &quot;protocols&quot; to ensure certain operations work.\n<em>That means that not every value that is declared <code>Iterable<\/code> or <code>Iterator<\/code> in TypeScript will have those methods we mentioned above.<\/em><\/p>\n<p>But there is still a new <strong>runtime value<\/strong> called <code>Iterator<\/code>.\nYou can reference <code>Iterator<\/code>, as well as <code>Iterator.prototype<\/code>, as actual values in JavaScript.\nThis is a bit awkward since TypeScript already defines its own thing called <code>Iterator<\/code> purely for type-checking.\nSo due to this unfortunate name clash, TypeScript needs to introduce a separate type to describe these native\/built-in iterable iterators.<\/p>\n<p>TypeScript 5.6 introduces a new type called <code>BuiltinIterator<\/code>.\nIt is defined as follows:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>interface BuiltinIterator&lt;T, TReturn = any, TNext = any&gt; {\r\n    \/\/ ...\r\n}\r\n<\/code><\/pre>\n<p>Lots of built-in collections and methods produce this type, and both the core JavaScript and DOM types in <code>lib.d.ts<\/code>, along with <code>@types\/node<\/code>, have been updated to use this new type.<\/p>\n<p>Similarly, there is a <code>BuiltinAsyncIterator<\/code> type for parity.\n<code>AsyncIterator<\/code> does not yet exist as a runtime value in JavaScript that brings the same methods for <code>AsyncIterable<\/code>s, <a href=\"https:\/\/github.com\/tc39\/proposal-async-iterator-helpers\">but it is an active proposal<\/a> and this new type prepares for it.<\/p>\n<p>We&#8217;d like to thank <a href=\"https:\/\/github.com\/bakkot\">Kevin Gibbons<\/a> who contributed <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/58222\">the changes for these types<\/a>, and who is one of the co-authors of <a href=\"https:\/\/github.com\/tc39\/proposal-iterator-helpers\">the proposal<\/a>.<\/p>\n<h2 id=\"strict-builtin-iterator-checks-and---strictbuiltiniteratorreturn\">Strict Builtin Iterator Checks (and <code>--strictBuiltinIteratorReturn<\/code>)<\/h2>\n<p>When you call the <code>next()<\/code> method on an <code>Iterator&lt;T, TReturn&gt;<\/code>, it returns an object with a <code>value<\/code> and a <code>done<\/code> property.\nThis is modeled with the type <code>IteratorResult<\/code>.<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>type IteratorResult&lt;T, TReturn = any&gt; = IteratorYieldResult&lt;T&gt; | IteratorReturnResult&lt;TReturn&gt;;\r\n\r\ninterface IteratorYieldResult&lt;TYield&gt; {\r\n    done?: false;\r\n    value: TYield;\r\n}\r\n\r\ninterface IteratorReturnResult&lt;TReturn&gt; {\r\n    done: true;\r\n    value: TReturn;\r\n}\r\n<\/code><\/pre>\n<p>The naming here is inspired by the way a generator function works.\nGenerator functions can <code>yield<\/code> values, and then <code>return<\/code> a final value &#8211; but the types between the two can be unrelated.<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>function abc123() {\r\n    yield &quot;a&quot;;\r\n    yield &quot;b&quot;;\r\n    yield &quot;c&quot;;\r\n    return 123;\r\n}\r\n\r\nconst iter = abc123();\r\n\r\niter.next(); \/\/ { value: &quot;a&quot;, done: false }\r\niter.next(); \/\/ { value: &quot;b&quot;, done: false }\r\niter.next(); \/\/ { value: &quot;c&quot;, done: false }\r\niter.next(); \/\/ { value: 123, done: true }\r\n<\/code><\/pre>\n<p>With the new <code>BuiltinIterator<\/code> type, we discovered some difficulties in allowing safe implementations of <code>BuiltinIterator<\/code>s.\nAt the same time, there&#8217;s been a long standing unsafety with <code>IteratorResult<\/code> in cases where <code>TReturn<\/code> was <code>any<\/code> (the default!).\nFor example, let&#8217;s say we have an <code>IteratorResult&lt;string, any&gt;<\/code>.\nIf we end up reaching for the <code>value<\/code> of this type, we&#8217;ll end up with <code>string | any<\/code>, which is just <code>any<\/code>.<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>function* uppercase(iter: Iterator&lt;string, any&gt;) {\r\n    while (true) {\r\n        const { value, done } = iter.next();\r\n        yield value.toUppercase(); \/\/ oops! forgot to check for `done` first and misspelled `toUpperCase`\r\n\r\n        if (done) {\r\n            return;\r\n        }\r\n    }\r\n}\r\n<\/code><\/pre>\n<p>It would be hard to fix this on every <code>Iterator<\/code> today without introducing a lot of breaks, but we can at least fix it with most <code>BuiltinIterator<\/code>s that get created.<\/p>\n<p>TypeScript 5.6 introduces a new intrinsic type called <code>BuiltinIteratorReturn<\/code> and a new <code>--strict<\/code>-mode flag called <code>--strictBuiltinIteratorReturn<\/code>.\nWhenever <code>BuiltinIterator<\/code>s are used in places like <code>lib.d.ts<\/code>, they are always written with <code>BuiltinIteratorReturn<\/code> type for <code>TReturn<\/code>:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>interface Map&lt;K, V&gt; {\r\n    \/\/ ...\r\n\r\n    \/**\r\n     * Returns an iterable of key, value pairs for every entry in the map.\r\n     *\/\r\n    entries(): BuiltinIterator&lt;[K, V], BuiltinIteratorReturn&gt;;\r\n\r\n    \/**\r\n     * Returns an iterable of keys in the map\r\n     *\/\r\n    keys(): BuiltinIterator&lt;K, BuiltinIteratorReturn&gt;;\r\n\r\n    \/**\r\n     * Returns an iterable of values in the map\r\n     *\/\r\n    values(): BuiltinIterator&lt;V, BuiltinIteratorReturn&gt;;\r\n}\r\n<\/code><\/pre>\n<p>By default, <code>BuiltinIteratorReturn<\/code> is <code>any<\/code>, but when <code>--strictBuiltinIteratorReturn<\/code> is enabled (possibly via <code>--strict<\/code>), it is <code>undefined<\/code>.\nUnder this new mode, if we use <code>BuiltinIteratorReturn<\/code>, our earlier example now correctly errors:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>function* uppercase(iter: Iterator&lt;string, BuiltinIteratorReturn&gt;) {\r\n    while (true) {\r\n        const { value, done } = iter.next();\r\n        yield value.toUppercase();\r\n        \/\/    ~~~~~ ~~~~~~~~~~~\r\n        \/\/ error! \u2503      \u2503\r\n        \/\/        \u2503      \u2517\u2501 Property 'toUppercase' does not exist on type 'string'. Did you mean 'toUpperCase'?\r\n        \/\/        \u2503\r\n        \/\/        \u2517\u2501 'value' is possibly 'undefined'.\r\n\r\n        if (done) {\r\n            return;\r\n        }\r\n    }\r\n}\r\n<\/code><\/pre>\n<p>For more information, you can <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/58243\">read up on the feature here<\/a>.<\/p>\n<h2 id=\"support-for-arbitrary-module-identifiers\">Support for Arbitrary Module Identifiers<\/h2>\n<p>JavaScript allows modules to export bindings with invalid identifier names as string literals:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>const banana = &quot;\ud83c\udf4c&quot;;\r\n\r\nexport { banana as &quot;\ud83c\udf4c&quot; };\r\n<\/code><\/pre>\n<p>Likewise, it allows modules to grab imports with these arbitrary names and bind them to valid identifiers:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>import { &quot;\ud83c\udf4c&quot; as banana } from &quot;.\/foo&quot;\r\n\r\n\/**\r\n * om nom nom\r\n *\/\r\nfunction eat(food: string) {\r\n    console.log(&quot;Eating&quot;, food);\r\n};\r\n\r\neat(banana);\r\n<\/code><\/pre>\n<p>This seems like a cute party trick (if you&#8217;re as fun as we are at parties), but it has its uses for interoperability with other languages (typically via JavaScript\/WebAssembly boundaries), since other languages may have different rules for what constitutes a valid identifier.\nIt can also be useful for tools that generate code, like esbuild <a href=\"https:\/\/esbuild.github.io\/api\/#inject\">with its <code>inject<\/code> feature<\/a>.<\/p>\n<p>TypeScript 5.6 now allows you to use these arbitrary module identifiers in your code!\nWe&#8217;d like to thank <a href=\"https:\/\/github.com\/evanw\">Evan Wallace<\/a> who <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/58640\">contributed this change to TypeScript<\/a>!<\/p>\n<h2 id=\"the---nouncheckedsideeffectimports-option\">The <code>--noUncheckedSideEffectImports<\/code> Option<\/h2>\n<p>In JavaScript it&#8217;s possible to <code>import<\/code> a module without actually importing any values from it.<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>import &quot;some-module&quot;;\r\n<\/code><\/pre>\n<p>These imports are often called <em>side effect imports<\/em> because the only useful behavior they can provide is by executing some side effect (like registering a global variable, or adding a polyfill to a prototype).<\/p>\n<p>In TypeScript, this syntax has had a pretty strange quirk: if the <code>import<\/code> could be resolved to a valid source file, then TypeScript would load and check the file.\nOn the other hand, if no source file could be found, TypeScript would silently ignore the <code>import<\/code>!<\/p>\n<p>This is surprising behavior, but it partially stems from modeling patterns in the JavaScript ecosystem.\nFor example, this syntax has also been used with special loaders in bundlers to load CSS or other assets.\nYour bundler might be configured in such a way where you can include specific <code>.css<\/code> files by writing something like the following:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>import &quot;.\/button-component.css&quot;;\r\n\r\nexport function Button() {\r\n    \/\/ ...\r\n}\r\n<\/code><\/pre>\n<p>Still, this masks potential typos on side effect imports.\nThat&#8217;s why TypeScript 5.6 introduces a new compiler option called <code>--noUncheckedSideEffectImports<\/code>, to catch these cases.\nWhen <code>--noUncheckedSideEffectImports<\/code> is enabled, TypeScript will now error if it can&#8217;t find a source file for a side effect import.<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>import &quot;oops-this-module-does-not-exist&quot;;\r\n\/\/     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n\/\/ error: Cannot find module 'oops-this-module-does-not-exist' or its corresponding type declarations.\r\n<\/code><\/pre>\n<p>When enabling this option, some working code may now receive an error, like in the CSS example above.\nTo work around this, users who want to just write side effect <code>import<\/code>s for assets might be better served by writing what&#8217;s called an <em>ambient module declaration<\/em> with a wildcard specifier.\nIt would go in a global file and look something like the following:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>\/\/ .\/src\/globals.d.ts\r\n\r\n\/\/ Recognize all CSS files as module imports.\r\ndeclare module &quot;*.css&quot; {}\r\n<\/code><\/pre>\n<p>In fact, you might already have a file like this in your project!\nFor example, running something like <code>vite init<\/code> might create a similar <code>vite-env.d.ts<\/code>.<\/p>\n<p>While this option is currently off by default, we encourage users to give it a try!<\/p>\n<p>For more information, <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/58941\">check out the implementation here<\/a>.<\/p>\n<h2 id=\"the---nocheck-option\">The <code>--noCheck<\/code> Option<\/h2>\n<p>TypeScript 5.6 introduces a new compiler option, <code>--noCheck<\/code>, which allows you to skip type checking for all input files.\nThis avoids unnecessary type-checking when performing any semantic analysis necessary for emitting output files.<\/p>\n<p>One scenario for this is to separate JavaScript file generation from type-checking so that the two can be run as separate phases.\nFor example, you could run <code>tsc --noCheck<\/code> while iterating, and then <code>tsc --noEmit<\/code> for a thorough type check.\nYou could also run the two tasks in parallel, even in <code>--watch<\/code> mode, though note you&#8217;d probably want to specify a separate <code>--tsBuildInfoFile<\/code> path if you&#8217;re truly running them at the same time.<\/p>\n<p><code>--noCheck<\/code> is also useful for emitting declaration files in a similar fashion.\nIn a project where <code>--noCheck<\/code> is specified on a project that conforms to <code>--isolatedDeclarations<\/code>, TypeScript can quickly generate declaration files without  a type-checking pass.\nThe generated declaration files will rely purely on quick syntactic transformations.<\/p>\n<p>Note that in cases where <code>--noCheck<\/code> is specified, but a project does <em>not<\/em> use <code>--isolatedDeclarations<\/code>, TypeScript may still perform as much type-checking as possible to generate <code>.d.ts<\/code> files.\nIn this sense, <code>--noCheck<\/code> is a bit of a misnomer; however the process will be lazier than a full type-check, only calculating the types of unannotated declarations.\nThis should be much faster than a full type-check.<\/p>\n<p><code>noCheck<\/code> is also available via the TypeScript API as a standard option.\nInternally, <code>transpileModule<\/code> and <code>transpileDeclaration<\/code> already used <code>noCheck<\/code> to speed things up (at least as of TypeScript 5.5).\nNow any build tool should be able to leverage the flag, taking a variety of custom strategies to coordinate and speed up builds.<\/p>\n<p>For more information, see <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/58364\">the work done in TypeScript 5.5 to power up <code>noCheck<\/code> internally<\/a>, along with the relevant work to make it publicly available <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/58839\">on the command line<\/a> and<\/p>\n<h2 id=\"allow---build-with-intermediate-errors\">Allow <code>--build<\/code> with Intermediate Errors<\/h2>\n<p>TypeScript&#8217;s concept of <em>project references<\/em> allows you to organize your codebase into multiple projects and create dependencies between them.\nRunning the TypeScript compiler in <code>--build<\/code> mode (or <code>tsc -b<\/code> for short) is the built-in way of actually conducting that build across projects and figuring out which projects and files need to be compiled.<\/p>\n<p>Previously, using <code>--build<\/code> mode would assume <code>--noEmitOnError<\/code> and immediately stop the build if any errors were encountered.\nThis meant that &quot;downstream&quot; projects could never be checked and built if any of their &quot;upstream&quot; dependencies had build errors.\nIn theory, this is a very cromulent approach &#8211; if a project has errors, it is not necessarily in a coherent state for its dependencies.<\/p>\n<p>In reality, this sort of rigidity made things like upgrades a pain.\nFor example, if <code>projectB<\/code> depends on <code>projectA<\/code>, then people more familiar with <code>projectB<\/code> can&#8217;t proactively upgrade their code until their dependencies are upgraded.\nThey are blocked by work on upgrading <code>projectA<\/code> first.<\/p>\n<p>As of TypeScript 5.6, <code>--build<\/code> mode will continue to build projects even if there are intermediate errors in dependencies.\nIn the face of intermediate errors, they will be reported consistently and output files will be generated on a best-effort basis;\nhowever, the build will continue to completion on the specified project.<\/p>\n<p>Note that to accomplish this, TypeScript now always emits a <code>.tsbuildinfo<\/code> file for any project in a <code>--build<\/code> invocation (even if <code>--incremental<\/code>\/<code>--composite<\/code> is not specified).\nThis is to keep track of the state of how <code>--build<\/code> was invoked and what work needs to be performed in the future.<\/p>\n<p>You can <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/58838\">read more about this change here on the implementation<\/a>.<\/p>\n<h2 id=\"region-prioritized-diagnostics-in-editors\">Region-Prioritized Diagnostics in Editors<\/h2>\n<p>When TypeScript&#8217;s language service is asked for the <em>diagnostics<\/em> for a file (things like errors, suggestions, and deprecations), it would typically require checking the <em>entire file<\/em>.\nMost of the time this is fine, but in extremely large files it can incur a delay.\nThat can be frustrating because fixing a typo should feel like a quick operation, but can take <em>seconds<\/em> in a big-enough file.<\/p>\n<p>To address this, TypeScript 5.6 introduces a new feature called <em>region-prioritized diagnostics<\/em> or <em>region-prioritized checking<\/em>.\nInstead of just requesting diagnostics for a set of files, editors can now also provide a relevant region of a given file &#8211; and the intent is that this will typically be the region of the file that is currently visible to a user.\nThe TypeScript language server can then choose to provide two sets of diagnostics: one for the region, and one for the file in its entirety.\nThis allows editing to feel <em>way<\/em> more responsive in large files so you&#8217;re not waiting as long for thoes red squiggles to disappear.<\/p>\n<p>For some specific numbers, in our testing <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/blob\/7319968e90600102892a79142fb804bcbe384160\/src\/compiler\/checker.ts\">on TypeScript&#8217;s own <code>checker.ts<\/code><\/a>, a full semantic diagnostics response took 3330ms.\nIn contrast, the response for the first region-based diagnostics response took 143ms!\nWhile the remaining whole-file response took about 3200ms, this can make a huge difference for quick edits.<\/p>\n<p>This feature also includes quite a bit of work to also make diagnostics report more consistently throughout your experience.\nDue the way our type-checker leverages caching to avoid work, subsequent checks between the same types could often have a different (typically shorter) error message.\nTechnically, lazy out-of-order checking could cause diagnostics to report differently between two locations in an editor &#8211; even before this feature &#8211; but we didn&#8217;t want to exacerbate the issue.\nWith recent work, we&#8217;ve ironed out many of these error inconsistencies.<\/p>\n<p>Currently, this functionality is available in Visual Studio Code for TypeScript 5.6 and later.<\/p>\n<p>For more detailed information, <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/57842\">take a look at the implementation and write-up here<\/a>.<\/p>\n<h2 id=\"search-ancestor-configuration-files-for-project-ownership\">Search Ancestor Configuration Files for Project Ownership<\/h2>\n<p>When a TypeScript file is loaded in an editor using TSServer (like Visual Studio or VS Code), the editor will try to find the relevant <code>tsconfig.json<\/code> file that &quot;owns&quot; the file.\nTo do this, it walks up the directory tree from the file being edited, looking for any file named <code>tsconfig.json<\/code>.<\/p>\n<p>Previously, this search would stop at the first <code>tsconfig.json<\/code> file found.\nhowever, imagine a project structure like the following:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>project\/\r\n\u251c\u2500\u2500 src\/\r\n\u2502   \u251c\u2500\u2500 foo.ts\r\n\u2502   \u251c\u2500\u2500 foo-test.ts\r\n\u2502   \u251c\u2500\u2500 tsconfig.json\r\n\u2502   \u2514\u2500\u2500 tsconfig.test.json\r\n\u2514\u2500\u2500 tsconfig.json\r\n<\/code><\/pre>\n<p>Here, the idea is that <code>src\/tsconfig.json<\/code> is the &quot;main&quot; configuration file for the project, and <code>src\/tsconfig.test.json<\/code> is a configuration file for running tests.<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>\/\/ src\/tsconfig.json\r\n{\r\n    &quot;compilerOptions&quot;: {\r\n        &quot;outDir&quot;: &quot;..\/dist&quot;\r\n    },\r\n    &quot;exclude&quot;: [&quot;**\/*.test.ts&quot;]\r\n}\r\n<\/code><\/pre>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>\/\/ src\/tsconfig.test.json\r\n{\r\n    &quot;compilerOptions&quot;: {\r\n        &quot;outDir&quot;: &quot;..\/dist\/test&quot;\r\n    },\r\n    &quot;include&quot;: [&quot;**\/*.test.ts&quot;],\r\n    &quot;references&quot;: [\r\n        { &quot;path&quot;: &quot;.\/tsconfig.json&quot; }\r\n    ]\r\n}\r\n<\/code><\/pre>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>\/\/ tsconfig.json\r\n{\r\n    \/\/ This is a &quot;solution-style&quot; or &quot;multi-project root&quot; tsconfig.\r\n    \/\/ Instead of specifying any files, it just references all the actual projects.\r\n    &quot;files&quot;: [],\r\n    &quot;references&quot;: [\r\n        { &quot;path&quot;: &quot;.\/src\/tsconfig.json&quot; },\r\n        { &quot;path&quot;: &quot;.\/src\/tsconfig.test.json&quot; },\r\n    ]\r\n}\r\n<\/code><\/pre>\n<p>The problem here is that when editing <code>foo-test.ts<\/code>, the editor would find <code>project\/src\/tsconfig.json<\/code> as the &quot;owning&quot; configuration file &#8211; but that&#8217;s not the one we want!\nIf the walk stops at this point, that might not be desirable.\nThe only way to avoid this previously was to rename <code>src\/tsconfig.json<\/code> to something like <code>src\/tsconfig.src.json<\/code>, and then all files would hit the top-level <code>tsconfig.json<\/code> which references every possible project.<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>project\/\r\n\u251c\u2500\u2500 src\/\r\n\u2502   \u251c\u2500\u2500 foo.ts\r\n\u2502   \u251c\u2500\u2500 foo-test.ts\r\n\u2502   \u251c\u2500\u2500 tsconfig.src.json\r\n\u2502   \u2514\u2500\u2500 tsconfig.test.json\r\n\u2514\u2500\u2500 tsconfig.json\r\n<\/code><\/pre>\n<p>Instead of forcing developers to do this, TypeScript 5.6 now continues walking up the directory tree to find other appropriate <code>tsconfig.json<\/code> files for editor scenarios.\nThis can provide more flexibility in how projects are organized and how configuration files are structured.<\/p>\n<p>You can <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/57196\">get more specifics on the implementation on GitHub<\/a>.<\/p>\n<h2 id=\"notable-behavioral-changes\">Notable Behavioral Changes<\/h2>\n<p>This section highlights a set of noteworthy changes that should be acknowledged and understood as part of any upgrade.\nSometimes it will highlight deprecations, removals, and new restrictions.\nIt can also contain bug fixes that are functionally improvements, but which can also affect an existing build by introducing new errors.<\/p>\n<h3 id=\"libdts\"><code>lib.d.ts<\/code><\/h3>\n<p>Types generated for the DOM may have an impact on type-checking your codebase.\nFor more information, <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/issues\/58764\">see linked issues related to DOM and <code>lib.d.ts<\/code> updates for this version of TypeScript<\/a>.<\/p>\n<h3 id=\"tsbuildinfo-is-always-written\"><code>.tsbuildinfo<\/code> is Always Written<\/h3>\n<p>To enable <code>--build<\/code> to continue building projects even if there are intermediate errors in dependencies, and to support <code>--noCheck<\/code> on the command line, TypeScript now always emits a <code>.tsbuildinfo<\/code> file for any project in a <code>--build<\/code> invocation.\nThis happens regardless of whether <code>--incremental<\/code> is actually on.\n<a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/58626\">See more information here<\/a>.<\/p>\n<h3 id=\"respecting-file-extensions-and-packagejson-from-within-node_modules\">Respecting File Extensions and <code>package.json<\/code> from within <code>node_modules<\/code><\/h3>\n<p>Before Node.js implemented support for ECMAScript modules in v12, there was never a good way for TypeScript to know whether <code>.d.ts<\/code> files it found in <code>node_modules<\/code> represented JavaScript files authored as CommonJS or ECMAScript modules.\nWhen the vast majority of npm was CommonJS-only, this didn&#8217;t cause many problems &#8211; if in doubt, TypeScript could just assume that everything behaved like CommonJS.\nUnfortunately, if that assumption was wrong it could allow unsafe imports:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>\/\/ node_modules\/dep\/index.d.ts\r\nexport declare function doSomething(): void;\r\n\r\n\/\/ index.ts\r\n\/\/ Okay if &quot;dep&quot; is a CommonJS module, but fails if\r\n\/\/ it's an ECMAScript module - even in bundlers!\r\nimport dep from &quot;dep&quot;;\r\ndep.doSomething();\r\n<\/code><\/pre>\n<p>In practice, this didn&#8217;t come up very often.\nBut in the years since Node.js started supporting ECMAScript modules, the share of ESM on npm has grown.\nFortunately, Node.js also introduced a mechanism that can help TypeScript determine if a file is an ECMAScript module or a CommonJS module: the <code>.mjs<\/code> and <code>.cjs<\/code> file extensions and the <code>package.json<\/code> <code>&quot;type&quot;<\/code> field.\nTypeScript 4.7 added support for understanding these indicators, as well as authoring <code>.mts<\/code> and <code>.cts<\/code> files;\nhowever, TypeScript would <em>only<\/em> read those indicators under <code>--module node16<\/code> and <code>--module nodenext<\/code>, so the unsafe import above was still a problem for anyone using <code>--module esnext<\/code> and <code>--moduleResolution bundler<\/code>, for example.<\/p>\n<p>To solve this, whenever TypeScript encounters files beneath a <code>node_modules<\/code> directory, TypeScript 5.6 reads and stores module format information encoded by file extensions and <code>package.json<\/code> <code>&quot;type&quot;<\/code> in <em>all<\/em> <code>module<\/code> modes, and uses it to resolve ambiguities like the one in the example above in all modes (except for <code>amd<\/code>, <code>umd<\/code>, and <code>system<\/code>).<\/p>\n<p>A secondary effect of respecting this format information is that the format-specific TypeScript file extensions (<code>.mts<\/code> and <code>.cts<\/code>) or an explicitly set package.json <code>&quot;type&quot;<\/code> in your own project will <em>override<\/em> your <code>--module<\/code> option if it&#8217;s set to <code>commonjs<\/code> or <code>es2015<\/code> through <code>esnext<\/code>.\nPreviously, it was technically possible to produce CommonJS output into a <code>.mjs<\/code> file or vice versa:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>\/\/ main.mts\r\nexport default &quot;oops&quot;;\r\n\r\n\/\/ $ tsc --module commonjs main.mts\r\n\/\/ main.mjs\r\nObject.defineProperty(exports, &quot;__esModule&quot;, { value: true });\r\nexports.default = &quot;oops&quot;;\r\n<\/code><\/pre>\n<p>Now, <code>.mts<\/code> files (or <code>.ts<\/code> files in scope of a <code>package.json<\/code> with <code>&quot;type&quot;: &quot;module&quot;<\/code>) never emit CommonJS output, and <code>.cts<\/code> files (or <code>.ts<\/code> files in scope of a package.json with <code>&quot;type&quot;: &quot;commonjs&quot;<\/code>) never emit ESM output.<\/p>\n<p>Note that much of this behavior was provided in pre-release versions of TypeScript 5.5 (<a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/57896\">implementation details here<\/a>), but in 5.6 this behavior is only extended to files within <code>node_modules<\/code>.<\/p>\n<p>More details are available <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/58825\">on the change here<\/a>.<\/p>\n<h3 id=\"correct-override-checks-on-computed-properties\">Correct <code>override<\/code> Checks on Computed Properties<\/h3>\n<p>Previously, computed properties marked with <code>override<\/code> did not correctly check for the existence of a base class member.\nSimilarly, if you used <code>noImplicitOverride<\/code>, you would not get an error if you <em>forgot<\/em> to add an <code>override<\/code> modifier to a computed property.<\/p>\n<p>TypeScript 5.6 now correctly checks computed properties in both cases.<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>const foo = Symbol(&quot;foo&quot;);\r\nconst bar = Symbol(&quot;bar&quot;);\r\n\r\nclass Base {\r\n    [bar]() {}\r\n}\r\n\r\nclass Derived extends Base {\r\n    override [foo]() {}\r\n\/\/           ~~~~~\r\n\/\/ error: This member cannot have an 'override' modifier because it is not declared in the base class 'Base'.\r\n\r\n    [bar]() {}\r\n\/\/  ~~~~~\r\n\/\/ error under noImplicitOverride: This member must have an 'override' modifier because it overrides a member in the base class 'Base'.\r\n}\r\n<\/code><\/pre>\n<p>This fix was contributed thanks to <a href=\"https:\/\/github.com\/a-tarasyuk\">Oleksandr Tarasiuk<\/a> in <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/57146\">this pull request<\/a>.<\/p>\n<h2 id=\"whats-next\">What&#8217;s Next?<\/h2>\n<p>At this point, TypeScript 5.6 is what we&#8217;d call &quot;feature-stable&quot;.\nThe focus on TypeScript 5.6 will be bug fixes, polish, and certain low-risk editor features.\nWe&#8217;ll have a release candidate available in a bit over month, followed by a stable release soon after.\nIf you&#8217;re interested in planning around the release, be sure to <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/issues\/59250\">keep an eye on our iteration plan<\/a> which has target release dates and more.<\/p>\n<p>As a note: while the beta is a great way to try out the next version of TypeScript, you can also <a href=\"https:\/\/www.typescriptlang.org\/docs\/handbook\/nightly-builds.html\">try a nightly build<\/a> to get the most up-to-date version of TypeScript 5.6 up until our release candidate.\nOur nightlies are well-tested and can even be tested <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=ms-vscode.vscode-typescript-next\">solely in your editor<\/a>.<\/p>\n<p>So please try out the beta or a nightly release today and let us know what you think!<\/p>\n<p>Happy Hacking!<\/p>\n<p>&#8211; Daniel Rosenwasser and the TypeScript Team<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today we are excited to announce the availability of TypeScript 5.6 Beta. To get started using the beta, you can get it through NuGet, or through npm with the following command: npm install -D typescript@beta Here&#8217;s a quick list of what&#8217;s new in TypeScript 5.6! Disallowed Nullish and Truthy Checks Iterator Helper Methods Strict Builtin [&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-4381","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-typescript"],"acf":[],"blog_post_summary":"<p>Today we are excited to announce the availability of TypeScript 5.6 Beta. To get started using the beta, you can get it through NuGet, or through npm with the following command: npm install -D typescript@beta Here&#8217;s a quick list of what&#8217;s new in TypeScript 5.6! Disallowed Nullish and Truthy Checks Iterator Helper Methods Strict Builtin [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/4381","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=4381"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/4381\/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=4381"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/categories?post=4381"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/tags?post=4381"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}