{"id":4083,"date":"2023-11-20T09:42:03","date_gmt":"2023-11-20T17:42:03","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/typescript\/?p=4083"},"modified":"2023-11-20T09:42:03","modified_gmt":"2023-11-20T17:42:03","slug":"announcing-typescript-5-3","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-5-3\/","title":{"rendered":"Announcing TypeScript 5.3"},"content":{"rendered":"<p>Today we&#8217;re excited to announce the release of TypeScript 5.3!<\/p>\n<p>If you&#8217;re not familiar with <a href=\"https:\/\/typescriptlang.org\">TypeScript<\/a>, it&#8217;s a language that adds type syntax to JavaScript to bring type-checking.\nType-checking can catch all sorts of issues like typos and forgetting to check for <code>null<\/code> and <code>undefined<\/code>.\nBut types go beyond type-checking &#8211; the same analyses of TypeScript&#8217;s type-checker are used for rich editor tooling like auto-completion, code navigation, and refactorings.\nIn fact, if you&#8217;ve been writing JavaScript in editors like Visual Studio or VS Code, that experience is powered by TypeScript!<\/p>\n<p>To get started using TypeScript, 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\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=\"#resolution-mode-supported-in-all-module-modes\"><code>resolution-mode<\/code> Supported in All Module Modes<\/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=\"#settings-to-prefer-type-auto-imports\">Settings to Prefer <code>type<\/code> Auto-Imports<\/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>What&#8217;s New Since the Beta and RC?<\/h2>\n<p>Since <a href=\"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-5-3-rc\/\">the release candidate<\/a>, no major changes have taken place.<\/p>\n<p>Since <a href=\"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-5-3-rc\/\">the beta<\/a> was released, we&#8217;ve added <a href=\"#settings-to-prefer-type-auto-imports\">an option to prefer <code>type<\/code>-only auto-imports when possible<\/a>.<\/p>\n<p>The beta <a href=\"#resolution-mode-supported-in-all-module-modes\">permitted <code>resolution-mode<\/code> to be used across module resolution settings<\/a>, but did not document it.<\/p>\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>resolution-mode<\/code> Supported in All Module Modes<\/h2>\n<p>Previously, using <code>resolution-mode<\/code> was only allowed under the <code>moduleResolution<\/code> options <code>node16<\/code> and <code>nodenext<\/code>.\nTo make it easier to look up modules specifically for type purposes, <code>resolution-mode<\/code> now works appropriately in all other <code>moduleResolution<\/code> options like <code>bundler<\/code>, <code>node10<\/code>, and simply doesn&#8217;t error under <code>classic<\/code>.<\/p>\n<p>For more information, <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/55725\">see the implementing pull request<\/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\/55991\">This feature<\/a> was spearheaded <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/53681\">initial work<\/a> by <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<h2>Settings to Prefer <code>type<\/code> Auto-Imports<\/h2>\n<p>Previously when TypeScript generated auto-imports for something in a type position, it would add a <code>type<\/code> modifier based on your settings.\nFor example, when getting an auto-import on <code>Person<\/code> in the following:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>export let p: Person\r\n<\/code><\/pre>\n<p>TypeScript&#8217;s editing experience would usually add an import for <code>Person<\/code> as:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>import { Person } from &quot;.\/types&quot;;\r\n\r\nexport let p: Person\r\n<\/code><\/pre>\n<p>and under certain settings like <code>verbatimModuleSyntax<\/code>, it would add the <code>type<\/code> modifier:<\/p>\n<pre class=\"lang:default decode:true\" style=\"padding: 10px;border-radius: 10px;\"><code>import { type Person } from &quot;.\/types&quot;;\r\n\r\nexport let p: Person\r\n<\/code><\/pre>\n<p>However, maybe your codebase isn&#8217;t able to use some of these options; or you just have a preference for explicit <code>type<\/code> imports when possible.<\/p>\n<p><a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/56090\">With a recent change<\/a>, TypeScript now enables this to be an editor-specific option.\nIn Visual Studio Code, you can enable it in the UI under &quot;TypeScript \u203a Preferences: Prefer Type Only Auto Imports&quot;, or as the JSON configuration option <code>typescript.preferences.preferTypeOnlyAutoImports<\/code><\/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>While our iteration plan isn&#8217;t yet public, we&#8217;re already working on TypeScript 5.4.\nWe expect TypeScript 5.4 will have a stable release towards the end of February 2024.\nAnticipate more details to come here.<\/p>\n<p>Until then, we hope you can start using TypeScript 5.3 soon, and that it 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.3! If you&#8217;re not familiar with TypeScript, it&#8217;s a language that adds type syntax to JavaScript to bring type-checking. Type-checking can catch all sorts of issues like typos and forgetting to check for null and undefined. But types go beyond type-checking &#8211; the same analyses of [&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-4083","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.3! If you&#8217;re not familiar with TypeScript, it&#8217;s a language that adds type syntax to JavaScript to bring type-checking. Type-checking can catch all sorts of issues like typos and forgetting to check for null and undefined. But types go beyond type-checking &#8211; the same analyses of [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/4083","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=4083"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/4083\/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=4083"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/categories?post=4083"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/tags?post=4083"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}