{"id":4043,"date":"2023-10-03T09:06:28","date_gmt":"2023-10-03T17:06:28","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/typescript\/?p=4043"},"modified":"2023-10-03T15:02:55","modified_gmt":"2023-10-03T23:02:55","slug":"announcing-typescript-5-3-beta","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-5-3-beta\/","title":{"rendered":"Announcing TypeScript 5.3 Beta"},"content":{"rendered":"<p>Today we are excited to announce the availability of TypeScript 5.3 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.3!<\/p>\n<ul>\n<li><a href=\"#import-attributes\">Import Attributes<\/a><\/li>\n<li><a href=\"#stable-support-resolution-mode-in-import-types\">Stable Support <code>resolution-mode<\/code> in Import Types<\/a><\/li>\n<li><a href=\"#switch-true-narrowing\"><code>switch (true)<\/code> Narrowing<\/a><\/li>\n<li><a href=\"#narrowing-on-comparisons-to-booleans\">Narrowing On Comparisons to Booleans<\/a><\/li>\n<li><a href=\"#instanceof-narrowing-through-symbolhasinstance\"><code>instanceof<\/code> Narrowing Through <code>Symbol.hasInstance<\/code><\/a><\/li>\n<li><a href=\"#checks-for-super-property-accesses-on-instance-fields\">Checks for <code>super<\/code> Property Accesses on Instance Fields<\/a><\/li>\n<li><a href=\"#interactive-inlay-hints-for-types\">Interactive Inlay Hints for Types<\/a><\/li>\n<li><a href=\"#optimizations-by-skipping-jsdoc-parsing\">Optimizations by Skipping JSDoc Parsing<\/a><\/li>\n<li><a href=\"#optimizations-by-comparing-non-normalized-intersections\">Optimizations by Comparing Non-Normalized Intersections<\/a><\/li>\n<li><a href=\"#consolidation-between-tsserverlibraryjs-and-typescriptjs\">Consolidation Between <code>tsserverlibrary.js<\/code> and <code>typescript.js<\/code><\/a><\/li>\n<li><a href=\"#breaking-changes-and-correctness-improvements\">Breaking Changes and Correctness Improvements<\/a><\/li>\n<\/ul>\n<h2>Import Attributes<\/h2>\n<p>TypeScript 5.3 supports the latest updates to the <a href=\"https:\/\/github.com\/tc39\/proposal-import-attributes\">import attributes<\/a> proposal.<\/p>\n<p>One use-case of import attributes is to provide information about the expected format of a module to the runtime.<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>\/\/ We only want this to be interpreted as JSON,\r\n\/\/ not a runnable\/malicious JavaScript file with a `.json` extension.\r\nimport obj from &quot;.\/something.json&quot; with { type: &quot;json&quot; };\r\n<\/code><\/pre>\n<p>The contents of these attributes are not checked by TypeScript since they&#8217;re host-specific, and are simply left alone so that browsers and runtimes can handle them (and possibly error).<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>\/\/ TypeScript is fine with this.\r\n\/\/ But your browser? Probably not.\r\nimport * as foo from &quot;.\/foo.js&quot; with { type: &quot;fluffy bunny&quot; };\r\n<\/code><\/pre>\n<p>Dynamic <code>import()<\/code> calls can also use import attributes through a second argument.<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>const obj = await import(&quot;.\/something.json&quot;, {\r\n    with: { type: &quot;json&quot; }\r\n});\r\n<\/code><\/pre>\n<p>The expected type of that second argument is defined by a type called <code>ImportCallOptions<\/code>, which by default just expects a property called <code>with<\/code>.<\/p>\n<p>Note that import attributes are an evolution of an earlier proposal called <a href=\"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-4-5\/#import-assertions\">&quot;import assertions&quot;, which were implemented in TypeScript 4.5<\/a>.\nThe most obvious difference is the use of the <code>with<\/code> keyword over the <code>assert<\/code> keyword.\nBut the less-visible difference is that runtimes are now free to use attributes to guide the resolution and interpretation of import paths, whereas import assertions could only assert some characteristics after loading a module.<\/p>\n<p>Over time, TypeScript will be deprecating the old syntax for import assertions in favor of the proposed syntax for import attributes.\nExisting code using <code>assert<\/code> should migrate towards the <code>with<\/code> keyword.\nNew code that needs an import attribute should use <code>with<\/code> exclusively.<\/p>\n<p>We&#8217;d like to thank <a href=\"https:\/\/github.com\/a-tarasyuk\">Oleksandr Tarasiuk<\/a> for <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/54242\">implementing this proposal<\/a>!\nAnd we&#8217;d also like to call out <a href=\"https:\/\/github.com\/Kingwl\">Wenlu Wang<\/a> for their implementation of <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/40698\">import assertions<\/a>!<\/p>\n<h2>Stable Support <code>resolution-mode<\/code> in Import Types<\/h2>\n<p>In TypeScript 4.7, TypeScript added support for a <code>resolution-mode<\/code> attribute in <code>\/\/\/ &lt;reference types=&quot;...&quot; \/&gt;<\/code> to control whether a specifier should be resolved via <code>import<\/code> or <code>require<\/code> semantics.<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>\/\/\/ &lt;reference types=&quot;pkg&quot; resolution-mode=&quot;require&quot; \/&gt;\r\n\r\n\/\/ or\r\n\r\n\/\/\/ &lt;reference types=&quot;pkg&quot; resolution-mode=&quot;import&quot; \/&gt;\r\n<\/code><\/pre>\n<p>A corresponding field was added to import assertions on type-only imports as well;\nhowever, it was only supported in nightly versions of TypeScript.\nThe rationale was that in spirit, import <em>assertions<\/em> were not intended to guide module resolution.\nSo this feature was shipped experimentally in a nightly-only mode to get more feedback.<\/p>\n<p>But given that <em><a href=\"#import-attributes\">import attributes<\/a><\/em> can guide resolution, and that we&#8217;ve seen reasonable use-cases, TypeScript 5.3 now supports the <code>resolution-mode<\/code> attribute for <code>import type<\/code>.<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>\/\/ Resolve `pkg` as if we were importing with a `require()`\r\nimport type { TypeFromRequire } from &quot;pkg&quot; with {\r\n    &quot;resolution-mode&quot;: &quot;require&quot;\r\n};\r\n\r\n\/\/ Resolve `pkg` as if we were importing with an `import`\r\nimport type { TypeFromImport } from &quot;pkg&quot; with {\r\n    &quot;resolution-mode&quot;: &quot;import&quot;\r\n};\r\n\r\nexport interface MergedType extends TypeFromRequire, TypeFromImport {}\r\n<\/code><\/pre>\n<p>These import attributes can also be used on <code>import()<\/code> types.<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>export type TypeFromRequire =\r\n    import(&quot;pkg&quot;, { with: { &quot;resolution-mode&quot;: &quot;require&quot; } }).TypeFromRequire;\r\n\r\nexport type TypeFromImport =\r\n    import(&quot;pkg&quot;, { with: { &quot;resolution-mode&quot;: &quot;import&quot; } }).TypeFromImport;\r\n\r\nexport interface MergedType extends TypeFromRequire, TypeFromImport {}\r\n<\/code><\/pre>\n<p>For more information, <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/55725\">check out the change here<\/a><\/p>\n<h2><code>switch (true)<\/code> Narrowing<\/h2>\n<p>TypeScript 5.3 now can perform narrowing based on conditions in each <code>case<\/code> clause within a <code>switch (true)<\/code>.<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>function f(x: unknown) {\r\n    switch (true) {\r\n        case typeof x === &quot;string&quot;:\r\n            \/\/ 'x' is a 'string' here\r\n            console.log(x.toUpperCase());\r\n            \/\/ falls through...\r\n\r\n        case Array.isArray(x):\r\n            \/\/ 'x' is a 'string | any[]' here.\r\n            console.log(x.length);\r\n            \/\/ falls through...\r\n\r\n        default:\r\n          \/\/ 'x' is 'unknown' here.\r\n          \/\/ ...\r\n    }\r\n}\r\n<\/code><\/pre>\n<p><a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/53681\">This work<\/a> was contributed courtesy of <a href=\"https:\/\/github.com\/Andarist\">Mateusz Burzy\u0144ski<\/a>.\nWe&#8217;d like to extend a &quot;thank you!&quot; for this contribution.<\/p>\n<h2>Narrowing On Comparisons to Booleans<\/h2>\n<p>Occasionally you may find yourself performing a direct comparison with <code>true<\/code> or <code>false<\/code> in a condition.\nUsually these are unnecessary comparisons, but you might prefer it as a point of style, or to avoid certain issues around JavaScript truthiness.\nRegardless, previously TypeScript just didn&#8217;t recognize such forms when performing narrowing.<\/p>\n<p>TypeScript 5.3 now keeps up and understands these expressions when narrowing variables.<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>interface A {\r\n    a: string;\r\n}\r\n\r\ninterface B {\r\n    b: string;\r\n}\r\n\r\ntype MyType = A | B;\r\n\r\nfunction isA(x: MyType): x is A {\r\n    return &quot;a&quot; in x;\r\n}\r\n\r\nfunction someFn(x: MyType) {\r\n    if (isA(x) === true) {\r\n        console.log(x.a); \/\/ works!\r\n    }\r\n}\r\n<\/code><\/pre>\n<p>We&#8217;d like to thank <a href=\"https:\/\/github.com\/Andarist\">Mateusz Burzy\u0144ski<\/a> for <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/53681\">the pull request<\/a> that implemented this.<\/p>\n<h2><code>instanceof<\/code> Narrowing Through <code>Symbol.hasInstance<\/code><\/h2>\n<p>A slightly esoteric feature of JavaScript is that it is possible to override the behavior of the <code>instanceof<\/code> operator.\nTo do so, the value on the right side of the <code>instanceof<\/code> operator needs to have a specific method named by <code>Symbol.hasInstance<\/code>.<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>class Weirdo {\r\n    static [Symbol.hasInstance](testedValue) {\r\n        \/\/ wait, what?\r\n        return testedValue === undefined;\r\n    }\r\n}\r\n\r\n\/\/ false\r\nconsole.log(new Thing() instanceof Weirdo);\r\n\r\n\/\/ true\r\nconsole.log(undefined instanceof Weirdo);\r\n<\/code><\/pre>\n<p>To better model this behavior in <code>instanceof<\/code>, TypeScript now checks if such a <code>[Symbol.hasInstance]<\/code> method exists and is declared as a type predicate function.\nIf it does, the tested value on the left side of the <code>instanceof<\/code> operator will be narrowed appropriately by that type predicate.<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>interface PointLike {\r\n    x: number;\r\n    y: number;\r\n}\r\n\r\nclass Point implements PointLike {\r\n    x: number;\r\n    y: number;\r\n\r\n    constructor(x: number, y: number) {\r\n        this.x = x;\r\n        this.y = y;\r\n    }\r\n\r\n    distanceFromOrigin() {\r\n        return Math.sqrt(this.x ** 2 + this.y ** 2);\r\n    }\r\n\r\n    static [Symbol.hasInstance](val: unknown): val is PointLike {\r\n        return !!val &amp;&amp; typeof val === &quot;object&quot; &amp;&amp;\r\n            &quot;x&quot; in val &amp;&amp; &quot;y&quot; in val &amp;&amp;\r\n            typeof val.x === &quot;number&quot; &amp;&amp;\r\n            typeof val.y === &quot;number&quot;;\r\n    }\r\n}\r\n\r\n\r\nfunction f(value: unknown) {\r\n    if (value instanceof Point) {\r\n        \/\/ Can access both of these - correct!\r\n        value.x;\r\n        value.y;\r\n\r\n        \/\/ Can't access this - we have a 'PointLike',\r\n        \/\/ but we don't *actually* have a 'Point'.\r\n        value.distanceFromOrigin();\r\n    }\r\n}\r\n<\/code><\/pre>\n<p>As you can see in this example, <code>Point<\/code> defines its own <code>[Symbol.hasInstance]<\/code> method.\nIt actually acts as a custom type guard over a separate type called <code>PointLike<\/code>.\nIn the function <code>f<\/code>, we were able to narrow <code>value<\/code> down to a <code>PointLike<\/code> with <code>instanceof<\/code>, but <em>not<\/em> a <code>Point<\/code>.\nThat means that we can access the properties <code>x<\/code> and <code>y<\/code>, but not the method <code>distanceFromOrigin<\/code>.<\/p>\n<p>For more information, you can <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/55052\">read up on this change here<\/a>.<\/p>\n<h2>Checks for <code>super<\/code> Property Accesses on Instance Fields<\/h2>\n<p>In JavaScript, it&#8217;s possible to access a declaration in a base class through the <code>super<\/code> keyword.<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>class Base {\r\n    someMethod() {\r\n        console.log(&quot;Base method called!&quot;);\r\n    }\r\n}\r\n\r\nclass Derived extends Base {\r\n    someMethod() {\r\n        console.log(&quot;Derived method called!&quot;);\r\n        super.someMethod();\r\n    }\r\n}\r\n\r\nnew Derived().someMethod();\r\n\/\/ Prints:\r\n\/\/   Derived method called!\r\n\/\/   Base method called!\r\n<\/code><\/pre>\n<p>This is different from writing something like <code>this.someMethod()<\/code>, since that could invoke an overridden method.\nThis is a subtle distinction, made more subtle by the fact that often the two can be interchangeable if a declaration is never overridden at all.<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>class Base {\r\n    someMethod() {\r\n        console.log(&quot;someMethod called!&quot;);\r\n    }\r\n}\r\n\r\nclass Derived extends Base {\r\n    someOtherMethod() {\r\n        \/\/ These act identically.\r\n        this.someMethod();\r\n        super.someMethod();\r\n    }\r\n}\r\n\r\nnew Derived().someOtherMethod();\r\n\/\/ Prints:\r\n\/\/   someMethod called!\r\n\/\/   someMethod called!\r\n<\/code><\/pre>\n<p>The problem is using them interchangeably is that <code>super<\/code> only works on members declared on the prototype \u2014 <em>not<\/em> instance properties.\nThat means that if you wrote <code>super.someMethod()<\/code>, but <code>someMethod<\/code> was defined as a field, you&#8217;d get a runtime error!<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>class Base {\r\n    someMethod = () =&gt; {\r\n        console.log(&quot;someMethod called!&quot;);\r\n    }\r\n}\r\n\r\nclass Derived extends Base {\r\n    someOtherMethod() {\r\n        super.someMethod();\r\n    }\r\n}\r\n\r\nnew Derived().someOtherMethod();\r\n\/\/ \ud83d\udca5\r\n\/\/ Doesn't work because 'super.someMethod' is 'undefined'.\r\n<\/code><\/pre>\n<p>TypeScript 5.3 now more-closely inspects <code>super<\/code> property accesses\/method calls to see if they correspond to class fields.\nIf they do, we&#8217;ll now get a type-checking error.<\/p>\n<p><a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/54056\">This check<\/a> was contributed thanks to <a href=\"https:\/\/github.com\/Jack-Works\">Jack Works<\/a>!<\/p>\n<h2>Interactive Inlay Hints for Types<\/h2>\n<p>TypeScript&#8217;s inlay hints now support jumping to the definition of types!\nThis makes it easier to casually navigate your code.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/typescript\/wp-content\/uploads\/sites\/11\/2023\/10\/clickable-inlay-hints-for-types-5-3-beta.gif\" alt=\"Ctrl-clicking an inlay hint to jump to the definition of a parameter type.\"><\/p>\n<p>See more at <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/55141\">the implementation here<\/a>.<\/p>\n<p><!--\n# Triggerable Refactor to Convert to Template String\n\nhttps:\/\/github.com\/microsoft\/TypeScript\/pull\/54647\n\n--><\/p>\n<h2>Optimizations by Skipping JSDoc Parsing<\/h2>\n<p>When running TypeScript via <code>tsc<\/code>, the compiler will now avoid parsing JSDoc.\nThis drops parsing time on its own, but also reduces memory usage to store comments along with time spent in garbage collection.\nAll-in-all, you should see slightly faster compiles and quicker feedback in <code>--watch<\/code> mode.<\/p>\n<p><a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/52921\">The specific changes can be viewed here<\/a>.<\/p>\n<p>Because not every tool using TypeScript will need to store JSDoc (e.g. typescript-eslint and Prettier), this parsing strategy has been surfaced as part of the API itself.\nThis can enable these tools to gain the same memory and speed improvements we&#8217;ve brought to the TypeScript compiler.\nThe new options for comment parsing strategy are described in <code>JSDocParsingMode<\/code>.\nMore information is available <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/55739\">on this pull request<\/a>.<\/p>\n<h2>Optimizations by Comparing Non-Normalized Intersections<\/h2>\n<p>In TypeScript, unions and intersections always follow a specific form, where intersections can&#8217;t contain union types.\nThat means that when we create an intersection over a union like <code>A &amp; (B | C)<\/code>, that intersection will be normalized into <code>(A &amp; B) | (A &amp; C)<\/code>.\nStill, in some cases the type system will maintain the original form for display purposes.<\/p>\n<p>It turns out that the original form can be used for some clever fast-path comparisons between types.<\/p>\n<p>For example, let&#8217;s say we have <code>SomeType &amp; (Type1 | Type2 | ... | Type99999NINE)<\/code> and we want to see if that&#8217;s assignable to <code>SomeType<\/code>.\nRecall that we don&#8217;t really have an intersection as our source type \u2014 we have a union that looks like <code>(SomeType &amp; Type1) | (SomeType &amp; Type2) | ... |(SomeType &amp; Type99999NINE)<\/code>.\nWhen checking if a union is assignable to some target type, we have to check if <em>every<\/em> member of the union is assignable to the target type, and that can be very slow.<\/p>\n<p>In TypeScript 5.3, we peek at the original intersection form that we were able to tuck away.\nWhen we compare the types, we do a quick check to see if the target exists in any constituent of the source intersection.<\/p>\n<p>For more information, <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/55851\">see this pull request<\/a>.<\/p>\n<h2>Consolidation Between <code>tsserverlibrary.js<\/code> and <code>typescript.js<\/code><\/h2>\n<p>TypeScript itself ships two library files: <code>tsserverlibrary.js<\/code> and <code>typescript.js<\/code>.\nThere are certain APIs available only in <code>tsserverlibrary.js<\/code> (like the <code>ProjectService<\/code> API), which may be useful to some importers.\nStill, the two are distinct bundles with have a lot of overlap, duplicating code in the package.\nWhat&#8217;s more, it can be challenging to consistently use one over the other due to auto-imports or muscle memory.\nAccidentally loading both modules is far too easy, and code may not work properly on a different instance of the API.\nEven if it does work, loading a second bundle increases resource usage.<\/p>\n<p>Given this, we&#8217;ve decided to consolidate the two.\n<code>typescript.js<\/code> now contains what <code>tsserverlibrary.js<\/code> used to contain, and <code>tsserverlibrary.js<\/code> now simply re-exports <code>typescript.js<\/code>.\nComparing the before\/after of this consolidation, we saw the following reduction in package size:<\/p>\n<table>\n<thead>\n<tr>\n<th><\/th>\n<th>Before<\/th>\n<th>After<\/th>\n<th>Diff<\/th>\n<th>Diff (percent)<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Packed<\/td>\n<td>6.90 MiB<\/td>\n<td>5.48 MiB<\/td>\n<td>-1.42 MiB<\/td>\n<td>-20.61%<\/td>\n<\/tr>\n<tr>\n<td>Unpacked<\/td>\n<td>38.74 MiB<\/td>\n<td>30.41 MiB<\/td>\n<td>-8.33 MiB<\/td>\n<td>-21.50%<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<table>\n<thead>\n<tr>\n<th><\/th>\n<th>Before<\/th>\n<th>After<\/th>\n<th>Diff<\/th>\n<th>Diff (percent)<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>lib\/tsserverlibrary.d.ts<\/code><\/td>\n<td>570.95 KiB<\/td>\n<td>865.00 B<\/td>\n<td>-570.10 KiB<\/td>\n<td>-99.85%<\/td>\n<\/tr>\n<tr>\n<td><code>lib\/tsserverlibrary.js<\/code><\/td>\n<td>8.57 MiB<\/td>\n<td>1012.00 B<\/td>\n<td>-8.57 MiB<\/td>\n<td>-99.99%<\/td>\n<\/tr>\n<tr>\n<td><code>lib\/typescript.d.ts<\/code><\/td>\n<td>396.27 KiB<\/td>\n<td>570.95 KiB<\/td>\n<td>+174.68 KiB<\/td>\n<td>+44.08%<\/td>\n<\/tr>\n<tr>\n<td><code>lib\/typescript.js<\/code><\/td>\n<td>7.95 MiB<\/td>\n<td>8.57 MiB<\/td>\n<td>+637.53 KiB<\/td>\n<td>+7.84%<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>In other words, this is over a 20.5% reduction in package size.<\/p>\n<p>For more information, you can <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/55273\">see the work involved here<\/a>.<\/p>\n<h2>Breaking Changes and Correctness Improvements<\/h2>\n<h2><code>lib.d.ts<\/code> Changes<\/h2>\n<p>Types generated for the DOM may have an impact on your codebase.\nFor more information, <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/55798\">see the DOM updates for TypeScript 5.3<\/a>.<\/p>\n<h2>Checks for <code>super<\/code> Accesses on Instance Properties<\/h2>\n<p>TypeScript 5.3 now detects when the declaration referenced by a <code>super.<\/code> property access is a class field and issues an error.\nThis prevents errors that might occur at runtime.<\/p>\n<p><a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/54056\">See more on this change here<\/a>.<\/p>\n<h2>What&#8217;s Next?<\/h2>\n<p>At this point, TypeScript 5.3 is what we&#8217;d call &quot;feature-stable&quot;.\nThe focus on TypeScript 5.3 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\/55486\">keep an eye on our iteration plan<\/a> which has target release dates and more.<\/p>\n<p>As a note: while 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.3 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.3 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.3! Import Attributes Stable Support resolution-mode in Import Types switch (true) [&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-4043","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.3 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.3! Import Attributes Stable Support resolution-mode in Import Types switch (true) [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/4043","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=4043"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/4043\/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=4043"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/categories?post=4043"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/tags?post=4043"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}