{"id":4429,"date":"2024-09-09T09:13:26","date_gmt":"2024-09-09T17:13:26","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/typescript\/?p=4429"},"modified":"2024-09-09T09:13:26","modified_gmt":"2024-09-09T17:13:26","slug":"announcing-typescript-5-6","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-5-6\/","title":{"rendered":"Announcing TypeScript 5.6"},"content":{"rendered":"<p>Today we&#8217;re excited to announce the release of TypeScript 5.6!<\/p>\n<p>If you&#8217;re not familiar with TypeScript, it&#8217;s a language that builds on top of JavaScript by adding syntax for <em>types<\/em>.\nTypes describe the shapes we expect of our variables, parameters, and functions, and the TypeScript <em>type-checker<\/em> can help catch issues like typos, missing properties, and bad function calls before we even run our code.\nTypes also power TypeScript&#8217;s editor tooling like the auto-completion, code navigation, and refactorings that you might see in editors like Visual Studio and VS Code.\nIn fact, if you write JavaScript in either of those editors, that experience is powered by TypeScript!\nYou can learn more at <a href=\"https:\/\/www.typescriptlang.org\/\">the TypeScript website<\/a>.<\/p>\n<p>You can get started using TypeScript using npm with the following command:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px; border-radius: 10px;\"><code>npm install -D typescript\r\n<\/code><\/pre>\n<p>or <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.TypeScript.MSBuild\">through NuGet<\/a>.<\/p>\n<p><!-- Here's a quick list of what's new in TypeScript 5.6! * [Disallowed Nullish and Truthy Checks](#disallowed-nullish-and-truthy-checks) * [Iterator Helper Methods](#iterator-helper-methods) * [Strict Builtin Iterator Checks (and `--strictBuiltinIteratorReturn`)](#strict-builtin-iterator-checks-and---strictbuiltiniteratorreturn) * [Support for Arbitrary Module Identifiers](#support-for-arbitrary-module-identifiers) * [The `--noUncheckedSideEffectImports` Option](#the---nouncheckedsideeffectimports-option) * [The `--noCheck` Option](#the---nocheck-option) * [Allow `--build` with Intermediate Errors](#allow---build-with-intermediate-errors) * [Region-Prioritized Diagnostics in Editors](#region-prioritized-diagnostics-in-editors) * [Granular Commit Characters](#granular-commit-characters) * [Exclude Patterns for Auto-Imports](#exclude-patterns-for-auto-imports) * [Notable Behavioral Changes](#notable-behavioral-changes) * [`lib.d.ts`](#libdts) * [`.tsbuildinfo` is Always Written](#tsbuildinfo-is-always-written) * [Respecting File Extensions and `package.json` from within `node_modules`](#respecting-file-extensions-and-packagejson-from-within-node_modules) * [Correct `override` Checks on Computed Properties](#correct-override-checks-on-computed-properties) --><\/p>\n<h2 id=\"whats-new-since-the-beta-and-rc\">What&#8217;s New Since the Beta and RC?<\/h2>\n<p>Since TypeScript 5.6 beta, we reverted <a href=\"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-5-6-beta\/#search-ancestor-configuration-files-for-project-ownership\">a change around how TypeScript&#8217;s language service searched for <code>tsconfig.json<\/code> files<\/a>.\nPreviously the language service would keep walking up looking for every possible project file named <code>tsconfig.json<\/code> that might contain a file.\nBecause this could lead to opening many referenced projects, <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/59634\">we reverted the behavior<\/a> and are <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/59688\">investigating ways to bring back the behavior in TypeScript 5.7<\/a>.<\/p>\n<p>Additionally, several new types have been renamed since the beta.\nPreviously, TypeScript provided a single type called <code>BuiltinIterator<\/code> to describe every value backed by <code>Iterator.prototype<\/code>.\nIt has been renamed <code>IteratorObject<\/code>, has a different set of type parameters, and now has several subtypes like <code>ArrayIterator<\/code>, <code>MapIterator<\/code>, and more.<\/p>\n<p>A new flag called <code>--stopOnBuildErrors<\/code> has been added for <code>--build<\/code> mode.\nWhen a project builds with any errors, no other projects will continue to be built.\nThis provides something close to the behavior of previous versions of TypeScript <a href=\"#allow---build-with-intermediate-errors\">since TypeScript 5.6 always builds in the face of errors<\/a>.<\/p>\n<p>New editor functionality has been added such as <a href=\"#granular-commit-characters\">direct support for commit characters<\/a> and <a href=\"#exclude-patterns-for-auto-imports\">exclude patterns for auto-imports<\/a>.<\/p>\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: \"strict\" | \"loose\") {\r\n    if (strictness === \"loose\") {\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, \"strict\") || isValid(secondaryValue, \"strict\") ||\r\n    isValid(primaryValue, \"loose\" || isValid(secondaryValue, \"loose\"))\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: \"strict\" | \"loose\") {\r\n    if (strictness === \"loose\") {\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, \"strict\") || isValid(secondaryValue, \"strict\") ||\r\n    isValid(primaryValue, \"loose\" || isValid(secondaryValue, \"loose\"))\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>All these new methods work as long as you&#8217;re running on a newer JavaScript runtime, or you&#8217;re using a polyfill for the new <code>Iterator<\/code> object.<\/p>\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 &#8220;protocols&#8221; 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>IteratorObject<\/code>.\nIt is defined as follows:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px; border-radius: 10px;\"><code>interface IteratorObject&lt;T, TReturn = unknown, TNext = unknown&gt; extends Iterator&lt;T, TReturn, TNext&gt; {\r\n    [Symbol.iterator](): IteratorObject&lt;T, TReturn, TNext&gt;;\r\n}\r\n<\/code><\/pre>\n<p>Lots of built-in collections and methods produce subtypes of <code>IteratorObject<\/code>s (like <code>ArrayIterator<\/code>, <code>SetIterator<\/code>, <code>MapIterator<\/code>, and more), 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>AsyncIteratorObject<\/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 \"a\";\r\n    yield \"b\";\r\n    yield \"c\";\r\n    return 123;\r\n}\r\n\r\nconst iter = abc123();\r\n\r\niter.next(); \/\/ { value: \"a\", done: false }\r\niter.next(); \/\/ { value: \"b\", done: false }\r\niter.next(); \/\/ { value: \"c\", done: false }\r\niter.next(); \/\/ { value: 123, done: true }\r\n<\/code><\/pre>\n<p>With the new <code>IteratorObject<\/code> type, we discovered some difficulties in allowing safe implementations of <code>IteratorObject<\/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>IteratorObject<\/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>IteratorObject<\/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> (though you&#8217;ll see the more-specific <code>MapIterator<\/code>, <code>ArrayIterator<\/code>, <code>SetIterator<\/code> more often).<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px; border-radius: 10px;\"><code>interface MapIterator&lt;T&gt; extends IteratorObject&lt;T, BuiltinIteratorReturn, unknown&gt; {\r\n    [Symbol.iterator](): MapIterator&lt;T&gt;;\r\n}\r\n\r\n\/\/ ...\r\n\r\ninterface 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(): MapIterator&lt;[K, V]&gt;;\r\n\r\n    \/**\r\n     * Returns an iterable of keys in the map\r\n     *\/\r\n    keys(): MapIterator&lt;K&gt;;\r\n\r\n    \/**\r\n     * Returns an iterable of values in the map\r\n     *\/\r\n    values(): MapIterator&lt;V&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>You&#8217;ll typically see <code>BuiltinIteratorReturn<\/code> paired up with <code>IteratorObject<\/code> throughout <code>lib.d.ts<\/code>.\nIn general, we recommend being more explicit around the <code>TReturn<\/code> in your own code when possible.<\/p>\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 = \"\ud83c\udf4c\";\r\n\r\nexport { banana as \"\ud83c\udf4c\" };\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 { \"\ud83c\udf4c\" as banana } from \".\/foo\"\r\n\r\n\/**\r\n * om nom nom\r\n *\/\r\nfunction eat(food: string) {\r\n    console.log(\"Eating\", 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 \"some-module\";\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 \".\/button-component.css\";\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 \"oops-this-module-does-not-exist\";\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 \"*.css\" {}\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 necessary 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 &#8220;downstream&#8221; projects could never be checked and built if any of their &#8220;upstream&#8221; 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>If you want to stop the build on the first project with errors, you can use a new flag called <code>--stopOnBuildErrors<\/code>.\nThis can be useful when running in a CI environment, or when iterating on a project that&#8217;s heavily depended upon by other projects.<\/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=\"granular-commit-characters\">Granular Commit Characters<\/h2>\n<p>TypeScript&#8217;s language service now provides its own <em>commit characters<\/em> for each completion item.\nCommit characters are specific characters that, when typed, will automatically commit the currently-suggested completion item.<\/p>\n<p>What this means is that over time your editor will now more frequently commit to the currently-suggested completion item when you type certain characters.\nFor example, take the following code:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px; border-radius: 10px;\"><code>declare let food: {\r\n    eat(): any;\r\n}\r\n\r\nlet f = (foo\/**\/\r\n<\/code><\/pre>\n<p>If our cursor is at <code>\/**\/<\/code>, it&#8217;s unclear if the code we&#8217;re writing is going to be something like <code>let f = (food.eat())<\/code> or <code>let f = (foo, bar) =&gt; foo + bar<\/code>.\nYou could imagine that the editor might be able to auto-complete differently depending on which character we type out next.\nFor instance, if we type in the period\/dot character (<code>.<\/code>), we probably want the editor to complete with the variable <code>food<\/code>;\nbut if we type the comma character (<code>,<\/code>), we might be writing out a parameter in an arrow function.<\/p>\n<p>Unfortunately, previously TypeScript just signaled to editors that the current text might define a new parameter name so that <em>no<\/em> commit characters were safe.\nSo hitting a <code>.<\/code> wouldn&#8217;t do anything even if it was &#8220;obvious&#8221; that the editor should auto-complete with the word <code>food<\/code>.<\/p>\n<p>TypeScript now explicitly lists which characters are safe to commit for each completion item.\nWhile this won&#8217;t <em>immediately<\/em> change your day-to-day experience, editors that support these commit characters should see behavioral improvements over time.\nTo see those improvements right now, you can now <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=ms-vscode.vscode-typescript-next\">use the TypeScript nightly extension<\/a> with <a href=\"https:\/\/code.visualstudio.com\/insiders\/\">Visual Studio Code Insiders<\/a>.\nHitting <code>.<\/code> in the code above correctly auto-completes with <code>food<\/code>.<\/p>\n<p>For more information, see <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/59339\">the pull request that added commit characters<\/a> along with our <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/59523\">adjustments to commit characters depending on context<\/a>.<\/p>\n<h2 id=\"exclude-patterns-for-auto-imports\">Exclude Patterns for Auto-Imports<\/h2>\n<p>TypeScript&#8217;s language service now allows you to specify a list of regular expression patterns which will filter away auto-import suggestions from certain specifiers.\nFor example, if you want to exclude all &#8220;deep&#8221; imports from a package like <code>lodash<\/code>, you could configure the following preference in Visual Studio Code:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px; border-radius: 10px;\"><code>{\r\n    \"typescript.preferences.autoImportSpecifierExcludeRegexes\": [\r\n        \"^lodash\/.*$\"\r\n    ]\r\n}\r\n<\/code><\/pre>\n<p>Or going the other way, you might want to disallow importing from the entry-point of a package:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px; border-radius: 10px;\"><code>{\r\n    \"typescript.preferences.autoImportSpecifierExcludeRegexes\": [\r\n        \"^lodash$\"\r\n    ]\r\n}\r\n<\/code><\/pre>\n<p>One could even avoid <code>node:<\/code> imports by using the following setting:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px; border-radius: 10px;\"><code>{\r\n    \"typescript.preferences.autoImportSpecifierExcludeRegexes\": [\r\n        \"^node:\"\r\n    ]\r\n}\r\n<\/code><\/pre>\n<p>To specify certain regular expression flags like <code>i<\/code> or <code>u<\/code>, you will need to surround your regular expression with slashes.\nWhen providing surrounding slashes, you&#8217;ll need to escape other inner slashes.<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px; border-radius: 10px;\"><code>{\r\n    \"typescript.preferences.autoImportSpecifierExcludeRegexes\": [\r\n        \"^.\/lib\/internal\",        \/\/ no escaping needed\r\n        \"\/^.\\\\\/lib\\\\\/internal\/\",  \/\/ escaping needed - note the leading and trailing slashes\r\n        \"\/^.\\\\\/lib\\\\\/internal\/i\"  \/\/ escaping needed - we needed slashes to provide the 'i' regex flag\r\n    ]\r\n}\r\n<\/code><\/pre>\n<p>The same settings can be applied for JavaScript through <code>javascript.preferences.autoImportSpecifierExcludeRegexes<\/code> in VS Code.<\/p>\n<p>Note that while this option may overlap a bit with <code>typescript.preferences.autoImportFileExcludePatterns<\/code>, there are differences.\nThe existing <code>autoImportFileExcludePatterns<\/code> takes a list of glob patterns that exclude <em>file paths<\/em>.\nThis might be simpler for a lot of scenarios where you want to avoid auto-importing from specific files and directories, but that&#8217;s not always enough.\nFor example, if you&#8217;re using the package <code>@types\/node<\/code>, the same file declares both <code>fs<\/code> and <code>node:fs<\/code>, so we can&#8217;t use <code>autoImportExcludePatterns<\/code> to filter out one or the other.<\/p>\n<p>The new <code>autoImportSpecifierExcludeRegexes<\/code> is specific to <em>module specifiers<\/em> (the specific string we write in our <code>import<\/code> statements), so we could write a pattern to exclude <code>fs<\/code> or <code>node:fs<\/code> without excluding the other.\nWhat&#8217;s more, we could write patterns to force auto-imports to prefer different specifier styles (e.g. preferring <code>.\/foo\/bar.js<\/code> over <code>#foo\/bar.js<\/code>).<\/p>\n<p>For more information, <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/59543\">see the implementation here<\/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 \"dep\" is a CommonJS module, but fails if\r\n\/\/ it's an ECMAScript module - even in bundlers!\r\nimport dep from \"dep\";\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>\"type\"<\/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, TypeScript 5.6 collects module format information and uses it to resolve ambiguities like the one in the example above in <em>all<\/em> <code>module<\/code> modes (except <code>amd<\/code>, <code>umd<\/code>, and <code>system<\/code>).\nFormat-specific file extensions (<code>.mts<\/code> and <code>.cts<\/code>) are respected anywhere they&#8217;re found, and the <code>package.json<\/code> <code>\"type\"<\/code> field is consulted inside <code>node_modules<\/code> dependencies, regardless of the <code>module<\/code> setting.\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 \"oops\";\r\n\r\n\/\/ $ tsc --module commonjs main.mts\r\n\/\/ main.mjs\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.default = \"oops\";\r\n<\/code><\/pre>\n<p>Now, <code>.mts<\/code> files never emit CommonJS output, and <code>.cts<\/code> files 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(\"foo\");\r\nconst bar = Symbol(\"bar\");\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>If you want to see what&#8217;s coming next, you can also take a look at <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/issues\/59905\">the TypeScript 5.7 iteration plan<\/a> where you&#8217;ll see a list of prioritized features, bug fixes, and target release dates that you can plan around.\n<a href=\"https:\/\/www.typescriptlang.org\/docs\/handbook\/nightly-builds.html\">TypeScript&#8217;s nightly releases<\/a> are easy to use over npm, and there&#8217;s also <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=ms-vscode.vscode-typescript-next\">an extension to use those nightly releases in Visual Studio Code<\/a>.\nNightly releases tend not to be disruptive, but they can give you a good sense of what&#8217;s coming next while helping the TypeScript project catch bugs early!<\/p>\n<p>Otherwise, we hope TypeScript 5.6 gives you a great experience, and makes your day-to-day coding a joy!<\/p>\n<p>Happy Hacking!<\/p>\n<p>&#8211; Daniel Rosenwasser and the TypeScript Team<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today we&#8217;re excited to announce the release of TypeScript 5.6! If you&#8217;re not familiar with TypeScript, it&#8217;s a language that builds on top of JavaScript by adding syntax for types. Types describe the shapes we expect of our variables, parameters, and functions, and the TypeScript type-checker can help catch issues like typos, missing properties, and [&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-4429","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-typescript"],"acf":[],"blog_post_summary":"<p>Today we&#8217;re excited to announce the release of TypeScript 5.6! If you&#8217;re not familiar with TypeScript, it&#8217;s a language that builds on top of JavaScript by adding syntax for types. Types describe the shapes we expect of our variables, parameters, and functions, and the TypeScript type-checker can help catch issues like typos, missing properties, and [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/4429","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=4429"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/4429\/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=4429"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/categories?post=4429"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/tags?post=4429"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}