{"id":3929,"date":"2023-05-18T13:31:53","date_gmt":"2023-05-18T21:31:53","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/typescript\/?p=3929"},"modified":"2023-05-18T13:31:53","modified_gmt":"2023-05-18T21:31:53","slug":"announcing-typescript-5-1-rc","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-5-1-rc\/","title":{"rendered":"Announcing TypeScript 5.1 RC"},"content":{"rendered":"<p>Today we&#8217;re excited to announce our Release Candidate of TypeScript 5.1!\nBetween now and the stable release of TypeScript 5.1, we expect no further changes apart from critical bug fixes.<\/p>\n<p>To get started using the RC, you can get it <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.TypeScript.MSBuild\">through NuGet<\/a>, or through npm with the following command:<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span>npm install -D typescript@rc<\/span>\r\n<\/code><\/pre>\n<p>Here&#8217;s a quick list of what&#8217;s new in TypeScript 5.1!<\/p>\n<ul>\n<li><a href=\"#easier-implicit-returns-for-undefined-returning-functions\">Easier Implicit Returns for <code>undefined<\/code>-Returning Functions<\/a><\/li>\n<li><a href=\"#unrelated-types-for-getters-and-setters\">Unrelated Types for Getters and Setters<\/a><\/li>\n<li><a href=\"#decoupled-type-checking-between-jsx-elements-and-jsx-tag-types\">Decoupled Type-Checking Between JSX Elements and JSX Tag Types<\/a><\/li>\n<li><a href=\"#namespaced-jsx-attributes\">Namespaced JSX Attributes<\/a><\/li>\n<li><a href=\"#typeroots-are-consulted-in-module-resolution\"><code>typeRoots<\/code> Are Consulted In Module Resolution<\/a><\/li>\n<li><a href=\"#move-declarations-to-existing-files\">Move Declarations to Existing Files<\/a><\/li>\n<li><a href=\"#linked-cursors-for-jsx-tags\">Linked Cursors for JSX Tags<\/a><\/li>\n<li><a href=\"#snippet-completions-for-param-jsdoc-tags\">Snippet Completions for <code>@param<\/code> JSDoc Tags<\/a><\/li>\n<li><a href=\"#optimizations\">Optimizations<\/a><\/li>\n<li><a href=\"#breaking-changes\">Breaking Changes<\/a><\/li>\n<\/ul>\n<h2><a name=\"beta-delta\"><\/a> What&#8217;s New Since the Beta?<\/h2>\n<p>Since the beta, <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/issues\/54267\">we&#8217;ve corrected some of our behavior for <code>init<\/code> hooks in decorators<\/a> as the proposed behavior has been adjusted.\nWe&#8217;ve also <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/54218\">made changes to our emit behavior under <code>isolatedModules<\/code><\/a>, ensuring that script files are not rewritten to modules.\nThis also means that usage of the <code>transpileModule<\/code> API will also ensure script files are not interpreted as modules, as it assumes the usage of <code>isolatedModules<\/code>.<\/p>\n<p>On top of these changes, we&#8217;ve recently added new refactoring support for <a href=\"#move-declarations-to-existing-files\">moving declarations to existing files<\/a>.<\/p>\n<h2>Easier Implicit Returns for <code>undefined<\/code>-Returning Functions<\/h2>\n<p>In JavaScript, if a function finishes running without hitting a <code>return<\/code>, it returns the value <code>undefined<\/code>.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span>function<\/span><span> <\/span><span>foo<\/span><span>() {<\/span>\r\n<span>    <\/span><span>\/\/ no return<\/span>\r\n<span>}<\/span>\r\n\r\n<span>\/\/ x = undefined<\/span>\r\n<span>let<\/span><span> <\/span><span>x<\/span><span> = <\/span><span>foo<\/span><span>();<\/span>\r\n<\/code><\/pre>\n<p>However, in previous versions of TypeScript, the <em>only<\/em> functions that could have absolutely no return statements were <code>void<\/code>&#8211; and <code>any<\/code>-returning functions.\nThat meant that even if you explicitly said &quot;this function returns <code>undefined<\/code>&quot; you were forced to have at least one return statement.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span>\/\/ \u2705 fine - we inferred that 'f1' returns 'void'<\/span>\r\n<span>function<\/span><span> <\/span><span>f1<\/span><span>() {<\/span>\r\n<span>    <\/span><span>\/\/ no returns<\/span>\r\n<span>}<\/span>\r\n\r\n<span>\/\/ \u2705 fine - 'void' doesn't need a return statement<\/span>\r\n<span>function<\/span><span> <\/span><span>f2<\/span><span>(): <\/span><span>void<\/span><span> {<\/span>\r\n<span>    <\/span><span>\/\/ no returns<\/span>\r\n<span>}<\/span>\r\n\r\n<span>\/\/ \u2705 fine - 'any' doesn't need a return statement<\/span>\r\n<span>function<\/span><span> <\/span><span>f3<\/span><span>(): <\/span><span>any<\/span><span> {<\/span>\r\n<span>    <\/span><span>\/\/ no returns<\/span>\r\n<span>}<\/span>\r\n\r\n<span>\/\/ \u274c error!<\/span>\r\n<span>\/\/ A function whose declared type is neither 'void' nor 'any' must return a value.<\/span>\r\n<span>function<\/span><span> <\/span><span>f4<\/span><span>(): <\/span><span>undefined<\/span><span> {<\/span>\r\n<span>    <\/span><span>\/\/ no returns<\/span>\r\n<span>}<\/span>\r\n<\/code><\/pre>\n<p>This could be a pain if some API expected a function returning <code>undefined<\/code> &#8211; you would need to have either at least one explicit return of <code>undefined<\/code> or a <code>return<\/code> statement <em>and<\/em> an explicit annotation.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span>declare<\/span><span> <\/span><span>function<\/span><span> <\/span><span>takesFunction<\/span><span>(<\/span><span>f<\/span><span>: () <\/span><span>=&gt;<\/span><span> <\/span><span>undefined<\/span><span>): <\/span><span>undefined<\/span><span>;<\/span>\r\n\r\n<span>\/\/ \u274c error!<\/span>\r\n<span>\/\/ Argument of type '() =&gt; void' is not assignable to parameter of type '() =&gt; undefined'.<\/span>\r\n<span>takesFunction<\/span><span>(() <\/span><span>=&gt;<\/span><span> {<\/span>\r\n<span>    <\/span><span>\/\/ no returns<\/span>\r\n<span>});<\/span>\r\n\r\n<span>\/\/ \u274c error!<\/span>\r\n<span>\/\/ A function whose declared type is neither 'void' nor 'any' must return a value.<\/span>\r\n<span>takesFunction<\/span><span>((): <\/span><span>undefined<\/span><span> <\/span><span>=&gt;<\/span><span> {<\/span>\r\n<span>    <\/span><span>\/\/ no returns<\/span>\r\n<span>});<\/span>\r\n\r\n<span>\/\/ \u274c error!<\/span>\r\n<span>\/\/ Argument of type '() =&gt; void' is not assignable to parameter of type '() =&gt; undefined'.<\/span>\r\n<span>takesFunction<\/span><span>(() <\/span><span>=&gt;<\/span><span> {<\/span>\r\n<span>    <\/span><span>return<\/span><span>;<\/span>\r\n<span>});<\/span>\r\n\r\n<span>\/\/ \u2705 works<\/span>\r\n<span>takesFunction<\/span><span>(() <\/span><span>=&gt;<\/span><span> {<\/span>\r\n<span>    <\/span><span>return<\/span><span> <\/span><span>undefined<\/span><span>;<\/span>\r\n<span>});<\/span>\r\n\r\n<span>\/\/ \u2705 works<\/span>\r\n<span>takesFunction<\/span><span>((): <\/span><span>undefined<\/span><span> <\/span><span>=&gt;<\/span><span> {<\/span>\r\n<span>    <\/span><span>return<\/span><span>;<\/span>\r\n<span>});<\/span>\r\n<\/code><\/pre>\n<p>This behavior was frustrating and confusing, especially when calling functions outside of one&#8217;s control.\nUnderstanding the interplay between inferring <code>void<\/code> over <code>undefined<\/code>, whether an <code>undefined<\/code>-returning function needs a <code>return<\/code> statement, etc. seems like a distraction.<\/p>\n<p>First, TypeScript 5.1 now allows <code>undefined<\/code>-returning functions to have no return statement.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span>\/\/ \u2705 Works in TypeScript 5.1!<\/span>\r\n<span>function<\/span><span> <\/span><span>f4<\/span><span>(): <\/span><span>undefined<\/span><span> {<\/span>\r\n<span>    <\/span><span>\/\/ no returns<\/span>\r\n<span>}<\/span>\r\n\r\n<span>\/\/ \u2705 Works in TypeScript 5.1!<\/span>\r\n<span>takesFunction<\/span><span>((): <\/span><span>undefined<\/span><span> <\/span><span>=&gt;<\/span><span> {<\/span>\r\n<span>    <\/span><span>\/\/ no returns<\/span>\r\n<span>});<\/span>\r\n<\/code><\/pre>\n<p>Second, if a function has no return expressions and is being passed to something expecting a function that returns <code>undefined<\/code>, TypeScript infers <code>undefined<\/code> for that function&#8217;s return type.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span>\/\/ \u2705 Works in TypeScript 5.1!<\/span>\r\n<span>takesFunction<\/span><span>(<\/span><span>function<\/span><span> <\/span><span>f<\/span><span>() {<\/span>\r\n<span>    <\/span><span>\/\/                 ^ return type is undefined<\/span>\r\n\r\n<span>    <\/span><span>\/\/ no returns<\/span>\r\n<span>});<\/span>\r\n\r\n<span>\/\/ \u2705 Works in TypeScript 5.1!<\/span>\r\n<span>takesFunction<\/span><span>(<\/span><span>function<\/span><span> <\/span><span>f<\/span><span>() {<\/span>\r\n<span>    <\/span><span>\/\/                 ^ return type is undefined<\/span>\r\n\r\n<span>    <\/span><span>return<\/span><span>;<\/span>\r\n<span>});<\/span>\r\n<\/code><\/pre>\n<p>To address another similar pain-point, under TypeScript&#8217;s <code>--noImplicitReturns<\/code> option, functions returning <em>only<\/em> <code>undefined<\/code> now have a similar exception to <code>void<\/code>, in that not every single code path must end in an explicit <code>return<\/code>.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span>\/\/ \u2705 Works in TypeScript 5.1 under '--noImplicitReturns'!<\/span>\r\n<span>function<\/span><span> <\/span><span>f<\/span><span>(): <\/span><span>undefined<\/span><span> {<\/span>\r\n<span>    <\/span><span>if<\/span><span> (<\/span><span>Math<\/span><span>.<\/span><span>random<\/span><span>()) {<\/span>\r\n<span>        <\/span><span>\/\/ do some stuff...<\/span>\r\n<span>        <\/span><span>return<\/span><span>;<\/span>\r\n<span>    }<\/span>\r\n<span>}<\/span>\r\n<\/code><\/pre>\n<p>For more information, you can read up on <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/issues\/36288\">the original issue<\/a> and <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/53607\">the implementing pull request<\/a>.<\/p>\n<h2>Unrelated Types for Getters and Setters<\/h2>\n<p>TypeScript 4.3 made it possible to say that a <code>get<\/code> and <code>set<\/code> accessor pair might specify two different types.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span>interface<\/span><span> <\/span><span>Serializer<\/span><span> {<\/span>\r\n<span>    <\/span><span>set<\/span><span> <\/span><span>value<\/span><span>(<\/span><span>v<\/span><span>: <\/span><span>string<\/span><span> | <\/span><span>number<\/span><span> | <\/span><span>boolean<\/span><span>);<\/span>\r\n<span>    <\/span><span>get<\/span><span> <\/span><span>value<\/span><span>(): <\/span><span>string<\/span><span>;<\/span>\r\n<span>}<\/span>\r\n\r\n<span>declare<\/span><span> <\/span><span>let<\/span><span> <\/span><span>box<\/span><span>: <\/span><span>Serializer<\/span><span>;<\/span>\r\n\r\n<span>\/\/ Allows writing a 'boolean'<\/span>\r\n<span>box<\/span><span>.<\/span><span>value<\/span><span> = <\/span><span>true<\/span><span>;<\/span>\r\n\r\n<span>\/\/ Comes out as a 'string'<\/span>\r\n<span>console<\/span><span>.<\/span><span>log<\/span><span>(<\/span><span>box<\/span><span>.<\/span><span>value<\/span><span>.<\/span><span>toUpperCase<\/span><span>());<\/span>\r\n<\/code><\/pre>\n<p>Initially we required that the <code>get<\/code> type had to be a subtype of the <code>set<\/code> type.\nThis meant that writing<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span>box<\/span><span>.<\/span><span>value<\/span><span> = <\/span><span>box<\/span><span>.<\/span><span>value<\/span><span>;<\/span>\r\n<\/code><\/pre>\n<p>would always be valid.<\/p>\n<p>However, there are plenty of existing and proposed APIs that have completely unrelated types between their getters and setters.\nFor example, consider one of the most common examples &#8211; the <code>style<\/code> property in the DOM and <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/CSSStyleRule\"><code>CSSStyleRule<\/code><\/a> API.\nEvery style rule has <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/CSSStyleRule\/style\">a <code>style<\/code> property<\/a> that is a <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/CSSStyleDeclaration\"><code>CSSStyleDeclaration<\/code><\/a>;\nhowever, if you try to write to that property, it will only work correctly with a string!<\/p>\n<p>TypeScript 5.1 now allows completely unrelated types for <code>get<\/code> and <code>set<\/code> accessor properties, provided that they have explicit type annotations.\nAnd while this version of TypeScript does not yet change the types for these built-in interfaces, <code>CSSStyleRule<\/code> can now be defined in the following way:<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span>interface<\/span><span> <\/span><span>CSSStyleRule<\/span><span> {<\/span>\r\n<span>    <\/span><span>\/\/ ...<\/span>\r\n\r\n<span>    <\/span><span>\/** Always reads as a `CSSStyleDeclaration` *\/<\/span>\r\n<span>    <\/span><span>get<\/span><span> <\/span><span>style<\/span><span>(): <\/span><span>CSSStyleDeclaration<\/span><span>;<\/span>\r\n\r\n<span>    <\/span><span>\/** Can only write a `string` here. *\/<\/span>\r\n<span>    <\/span><span>set<\/span><span> <\/span><span>style<\/span><span>(<\/span><span>newValue<\/span><span>: <\/span><span>string<\/span><span>);<\/span>\r\n\r\n<span>    <\/span><span>\/\/ ...<\/span>\r\n<span>}<\/span>\r\n<\/code><\/pre>\n<p>This also allows other patterns like requiring <code>set<\/code> accessors to accept only &quot;valid&quot; data, but specifying that <code>get<\/code> accessors may return <code>undefined<\/code> if some underlying state hasn&#8217;t been initialized yet.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span>class<\/span><span> <\/span><span>SafeBox<\/span><span> {<\/span>\r\n<span>    <\/span><span>#value<\/span><span>: <\/span><span>string<\/span><span> | <\/span><span>undefined<\/span><span>;<\/span>\r\n\r\n<span>    <\/span><span>\/\/ Only accepts strings!<\/span>\r\n<span>    <\/span><span>set<\/span><span> <\/span><span>value<\/span><span>(<\/span><span>newValue<\/span><span>: <\/span><span>string<\/span><span>) {<\/span>\r\n\r\n<span>    }<\/span>\r\n\r\n<span>    <\/span><span>\/\/ Must check for 'undefined'!<\/span>\r\n<span>    <\/span><span>get<\/span><span> <\/span><span>value<\/span><span>(): <\/span><span>string<\/span><span> | <\/span><span>undefined<\/span><span> {<\/span>\r\n<span>        <\/span><span>return<\/span><span> <\/span><span>this<\/span><span>.<\/span><span>#value<\/span><span>;<\/span>\r\n<span>    }<\/span>\r\n<span>}<\/span>\r\n<\/code><\/pre>\n<p>In fact, this is similar to how optional properties are checked under <code>--exactOptionalProperties<\/code>.<\/p>\n<p>You can read up more on <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/53417\">the implementing pull request<\/a>.<\/p>\n<h2>Decoupled Type-Checking Between JSX Elements and JSX Tag Types<\/h2>\n<p>One pain point TypeScript had with JSX was its requirements on the type of every JSX element&#8217;s tag.<\/p>\n<p>For context, a JSX element is either of the following:<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span>\/\/ A self-closing JSX tag<\/span>\r\n<span>&lt;<\/span><span>Foo<\/span><span> <\/span><span>\/&gt;<\/span>\r\n\r\n<span>\/\/ A regular element with an opening\/closing tag<\/span>\r\n<span>&lt;<\/span><span>Bar<\/span><span>&gt;&lt;\/<\/span><span>Bar<\/span><span>&gt;<\/span>\r\n<\/code><\/pre>\n<p>When type-checking <code>&lt;Foo \/&gt;<\/code> or <code>&lt;Bar&gt;&lt;\/Bar&gt;<\/code>, TypeScript always looks up a namespace called <code>JSX<\/code> and fetches a type out of it called <code>Element<\/code> &#8211; or more directly, it looks up <code>JSX.Element<\/code>.<\/p>\n<p>But to check whether <code>Foo<\/code> or <code>Bar<\/code> themselves were valid to use as tag names, TypeScript would roughly just grab the types returned or constructed by <code>Foo<\/code> or <code>Bar<\/code> and check for compatibility with <code>JSX.Element<\/code> (or another type called <code>JSX.ElementClass<\/code> if the type is constructable).<\/p>\n<p>The limitations here meant that components could not be used if they returned or &quot;rendered&quot; a more broad type than just <code>JSX.Element<\/code>.\nFor example, a JSX library might be fine with a component returning <code>string<\/code>s or <code>Promise<\/code>s.<\/p>\n<p>As a more concrete example, <a href=\"https:\/\/github.com\/acdlite\/rfcs\/blob\/first-class-promises\/text\/0000-first-class-support-for-promises.md\">React is considering adding limited support for components that return <code>Promise<\/code>s<\/a>, but existing versions of TypeScript cannot express that without someone drastically loosening the type of <code>JSX.Element<\/code>.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span>import<\/span><span> <\/span><span>*<\/span><span> <\/span><span>as<\/span><span> <\/span><span>React<\/span><span> <\/span><span>from<\/span><span> <\/span><span>&quot;react&quot;<\/span><span>;<\/span>\r\n\r\n<span>async<\/span><span> <\/span><span>function<\/span><span> <\/span><span>Foo<\/span><span>() {<\/span>\r\n<span>    <\/span><span>return<\/span><span> <\/span><span>&lt;div&gt;&lt;\/div&gt;<\/span><span>;<\/span>\r\n<span>}<\/span>\r\n\r\n<span>let<\/span><span> <\/span><span>element<\/span><span> = <\/span><span>&lt;<\/span><span>Foo<\/span><span> <\/span><span>\/&gt;<\/span><span>;<\/span>\r\n<span>\/\/             ~~~<\/span>\r\n<span>\/\/ 'Foo' cannot be used as a JSX component.<\/span>\r\n<span>\/\/   Its return type 'Promise&lt;Element&gt;' is not a valid JSX element.<\/span>\r\n<\/code><\/pre>\n<p>To provide libraries with a way to express this, TypeScript 5.1 now looks up a type called <code>JSX.ElementType<\/code>.\n<code>ElementType<\/code> specifies precisely what is valid to use as a tag in a JSX element.\nSo it might be typed today as something like<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span>namespace<\/span><span> <\/span><span>JSX<\/span><span> {<\/span>\r\n<span>    <\/span><span>export<\/span><span> <\/span><span>type<\/span><span> <\/span><span>ElementType<\/span><span> =<\/span>\r\n<span>        <\/span><span>\/\/ All the valid lowercase tags<\/span>\r\n<span>        <\/span><span>keyof<\/span><span> <\/span><span>IntrinsicAttributes<\/span>\r\n<span>        <\/span><span>\/\/ Function components<\/span>\r\n<span>        (<\/span><span>props<\/span><span>: <\/span><span>any<\/span><span>) <\/span><span>=&gt;<\/span><span> <\/span><span>Element<\/span>\r\n<span>        <\/span><span>\/\/ Class components<\/span>\r\n<span>        <\/span><span>new<\/span><span> (<\/span><span>props<\/span><span>: <\/span><span>any<\/span><span>) <\/span><span>=&gt;<\/span><span> <\/span><span>ElementClass<\/span><span>;<\/span>\r\n\r\n<span>    <\/span><span>export<\/span><span> <\/span><span>interface<\/span><span> <\/span><span>IntrinsictAttributes<\/span><span> <\/span><span>extends<\/span><span> <\/span><span>\/*...*\/<\/span><span> {}<\/span>\r\n<span>    <\/span><span>export<\/span><span> <\/span><span>type<\/span><span> <\/span><span>Element<\/span><span> = <\/span><span>\/*...*\/<\/span><span>;<\/span>\r\n<span>    <\/span><span>export<\/span><span> <\/span><span>type<\/span><span> <\/span><span>ClassElement<\/span><span> = <\/span><span>\/*...*\/<\/span><span>;<\/span>\r\n<span>}<\/span>\r\n<\/code><\/pre>\n<p>We&#8217;d like to extend our thanks to <a href=\"https:\/\/github.com\/eps1lon\">Sebastian Silbermann<\/a> who contributed <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/51328\">this change<\/a>!<\/p>\n<h2>Namespaced JSX Attributes<\/h2>\n<p>TypeScript now supports namespaced attribute names when using JSX.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span>import<\/span><span> <\/span><span>*<\/span><span> <\/span><span>as<\/span><span> <\/span><span>React<\/span><span> <\/span><span>from<\/span><span> <\/span><span>&quot;react&quot;<\/span><span>;<\/span>\r\n\r\n<span>\/\/ Both of these are equivalent:<\/span>\r\n<span>const<\/span><span> <\/span><span>x<\/span><span> = <\/span><span>&lt;<\/span><span>Foo<\/span><span> <\/span><span>a<\/span><span>:<\/span><span>b<\/span><span>=<\/span><span>&quot;hello&quot;<\/span><span> <\/span><span>\/&gt;<\/span><span>;<\/span>\r\n<span>const<\/span><span> <\/span><span>y<\/span><span> = <\/span><span>&lt;<\/span><span>Foo<\/span><span> <\/span><span>a<\/span><span> <\/span><span>:<\/span><span> <\/span><span>b<\/span><span>=<\/span><span>&quot;hello&quot;<\/span><span> <\/span><span>\/&gt;<\/span><span>;<\/span>\r\n\r\n<span>interface<\/span><span> <\/span><span>FooProps<\/span><span> {<\/span>\r\n<span>    <\/span><span>&quot;a:b&quot;<\/span><span>: <\/span><span>string<\/span><span>;<\/span>\r\n<span>}<\/span>\r\n\r\n<span>function<\/span><span> <\/span><span>Foo<\/span><span>(<\/span><span>props<\/span><span>: <\/span><span>FooProps<\/span><span>) {<\/span>\r\n<span>    <\/span><span>return<\/span><span> <\/span><span>&lt;div&gt;<\/span><span>{<\/span><span>props<\/span><span>[<\/span><span>&quot;a:b&quot;<\/span><span>]<\/span><span>}<\/span><span>&lt;\/div&gt;<\/span><span>;<\/span>\r\n<span>}<\/span>\r\n<\/code><\/pre>\n<p>Namespaced tag names are looked up in a similar way on <code>JSX.IntrinsicAttributes<\/code> when the first segment of the name is a lowercase name.<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span>\/\/ In some library's code or in an augmentation of that library:<\/span>\r\n<span>namespace<\/span><span> <\/span><span>JSX<\/span><span> {<\/span>\r\n<span>    <\/span><span>interface<\/span><span> <\/span><span>IntrinsicElements<\/span><span> {<\/span>\r\n<span>        [<\/span><span>&quot;a:b&quot;<\/span><span>]: { <\/span><span>prop<\/span><span>: <\/span><span>string<\/span><span> };<\/span>\r\n<span>    }<\/span>\r\n<span>}<\/span>\r\n\r\n<span>\/\/ In our code:<\/span>\r\n<span>let<\/span><span> <\/span><span>x<\/span><span> = <\/span><span>&lt;a<\/span><span>:<\/span><span>b<\/span><span> <\/span><span>prop<\/span><span>=<\/span><span>&quot;hello!&quot;<\/span><span> <\/span><span>\/&gt;<\/span><span>;<\/span>\r\n<\/code><\/pre>\n<p><a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/53799\">This contribution<\/a> was provided thanks to <a href=\"https:\/\/github.com\/a-tarasyuk\">Oleksandr Tarasiuk<\/a>.<\/p>\n<h2><code>typeRoots<\/code> Are Consulted In Module Resolution<\/h2>\n<p>When TypeScript&#8217;s specified module lookup strategy is unable to resolve a path, it will now resolve packages relative to the specified <code>typeRoots<\/code>.<\/p>\n<p>See <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/51715\">this pull request<\/a> for more details.<\/p>\n<h2>Move Declarations to Existing Files<\/h2>\n<p>In addition to moving declarations to new files, TypeScript now ships a preview feature for moving declarations to existing files as well.\nYou can try this functionality out in a recent version of Visual Studio Code.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/typescript\/wp-content\/uploads\/sites\/11\/2023\/05\/moveToFile-5.1-preview.gif\" alt=\"Moving a function 'getThanks' to an existing file in the workspace.\"><\/p>\n<p>Keep in mind that this feature is currently in preview, and we are seeking further feedback on it.<\/p>\n<p><a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/53542\">https:\/\/github.com\/microsoft\/TypeScript\/pull\/53542<\/a><\/p>\n<h2>Linked Cursors for JSX Tags<\/h2>\n<p>TypeScript now supports <em>linked editing<\/em> for JSX tag names.\nLinked editing (occasionally called &quot;mirrored cursors&quot;) allows an editor to edit multiple locations at the same time automatically.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/typescript\/wp-content\/uploads\/sites\/11\/2023\/04\/linkedEditingJsx-5.1-1.gif\" alt=\"An example of JSX tags with linked editing modifying a JSX fragment and a div element.\"><\/p>\n<p>This new feature should work in both TypeScript and JavaScript files, and can be enabled in Visual Studio Code Insiders.\nIn Visual Studio Code, you can either edit the <code>Editor: Linked Editing<\/code> option in the Settings UI:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/typescript\/wp-content\/uploads\/sites\/11\/2023\/04\/linkedEditing-5.1-vscode-ui-1.png\" alt=\"Visual Studio Code's Editor: Linked Editing` option\"><\/p>\n<p>or configure <code>editor.linkedEditing<\/code> in your JSON settings file:<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span>{<\/span>\r\n<span>    <\/span><span>\/\/ ...<\/span>\r\n<span>    <\/span><span>&quot;editor.linkedEditing&quot;<\/span><span>: <\/span><span>true<\/span><span>,<\/span>\r\n<span>}<\/span>\r\n<\/code><\/pre>\n<p>This feature will also be supported by Visual Studio 17.7 Preview 1.<\/p>\n<p>You can take a look at <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/53284\">our implementation of linked editing<\/a> here!<\/p>\n<h2>Snippet Completions for <code>@param<\/code> JSDoc Tags<\/h2>\n<p>TypeScript now provides snippet completions when typing out a <code>@param<\/code> tag in both TypeScript and JavaScript files.\nThis can help cut down on some typing and jumping around text as you document your code or add JSDoc types in JavaScript.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/typescript\/wp-content\/uploads\/sites\/11\/2023\/04\/paramTagSnippets-5-1-1.gif\" alt=\"An example of completing JSDoc  comments on an 'add' function.\"><\/p>\n<p>You can <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/53260\">check out how this new feature was implemented on GitHub<\/a>.<\/p>\n<h2>Optimizations<\/h2>\n<h3>Avoiding Unnecessary Type Instantiation<\/h3>\n<p>TypeScript 5.1 now avoids performing type instantiation within object types that are known not to contain references to outer type parameters.\nThis has the potential to cut down on many unnecessary computations, and reduced the type-checking time of <a href=\"https:\/\/github.com\/mui\/material-ui\/tree\/b0351248fb396001a30330daac86d0e0794a0c1d\/docs\">material-ui&#8217;s docs directory<\/a> by over 50%.<\/p>\n<p>You can <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/53246\">see the changes involved for this change on GitHub<\/a>.<\/p>\n<h3>Negative Case Checks for Union Literals<\/h3>\n<p>When checking if a source type is part of a union type, TypeScript will first do a fast look-up using an internal type identifier for that source.\nIf that look-up fails, then TypeScript checks for compatibility against every type within the union.<\/p>\n<p>When relating a literal type to a union of purely literal types, TypeScript can now avoid that full walk against every other type in the union.\nThis assumption is safe because TypeScript always interns\/caches literal types &#8211; though there are some edge cases to handle relating to &quot;fresh&quot; literal types.<\/p>\n<p><a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/53192\">This optimization<\/a> was able to reduce the type-checking time of <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/issues\/53191\">the code in this issue<\/a> from about 45 seconds to about 0.4 seconds.<\/p>\n<h3>Reduced Calls into Scanner for JSDoc Parsing<\/h3>\n<p>When older versions of TypeScript parsed out a JSDoc comment, they would use the scanner\/tokenizer to break the comment into fine-grained tokens and piece the contents back together.\nThis could be helpful for normalizing comment text, so that multiple spaces would just collapse into one;\nbut it was extremely &quot;chatty&quot; and meant the parser and scanner would jump back and forth very often, adding overhead to JSDoc parsing.<\/p>\n<p>TypeScript 5.1 has moved more logic around breaking down JSDoc comments into the scanner\/tokenizer.\nThe scanner now returns larger chunks of content directly to the parser to do as it needs.<\/p>\n<p><a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/53081\">These changes<\/a> have brought down the parse time of several 10Mb mostly-prose-comment JavaScript files by about half.\nFor a more realistic example, our performance suite&#8217;s snapshot of <a href=\"https:\/\/github.com\/statelyai\/xstate\">xstate<\/a> dropped about 300ms of parse time, making it faster to load and analyze.<\/p>\n<h2>Breaking Changes<\/h2>\n<h3>ES2020 and Node.js 14.17 as Minimum Runtime Requirements<\/h3>\n<p>TypeScript 5.1 now ships JavaScript functionality that was introduced in ECMAScript 2020.\nAs a result, at minimum TypeScript must be run in a reasonably modern runtime.\nFor most users, this means TypeScript now only runs on Node.js 14.17 and later.<\/p>\n<p>If you try running TypeScript 5.1 under an older version of Node.js such as Node 10 or 12, you may see an error like the following from running either <code>tsc.js<\/code> or <code>tsserver.js<\/code>:<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span>node_modules\/typescript\/lib\/tsserver.js:2406<\/span>\r\n<span>  for (let i = startIndex ?? 0; i &lt; array.length; i++) {<\/span>\r\n<span>                           ^<\/span>\r\n<span> <\/span>\r\n<span>SyntaxError: Unexpected token '?'<\/span>\r\n<span>    at wrapSafe (internal\/modules\/cjs\/loader.js:915:16)<\/span>\r\n<span>    at Module._compile (internal\/modules\/cjs\/loader.js:963:27)<\/span>\r\n<span>    at Object.Module._extensions..js (internal\/modules\/cjs\/loader.js:1027:10)<\/span>\r\n<span>    at Module.load (internal\/modules\/cjs\/loader.js:863:32)<\/span>\r\n<span>    at Function.Module._load (internal\/modules\/cjs\/loader.js:708:14)<\/span>\r\n<span>    at Function.executeUserEntryPoint [as runMain] (internal\/modules\/run_main.js:60:12)<\/span>\r\n<span>    at internal\/main\/run_main_module.js:17:47<\/span>\r\n<span><\/span><\/code><\/pre>\n<p>Additionally, if you try installing TypeScript you&#8217;ll get something like the following error messages from npm:<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span>npm WARN EBADENGINE Unsupported engine {<\/span>\r\n<span>npm WARN EBADENGINE   package: 'typescript@5.1.1-rc',<\/span>\r\n<span>npm WARN EBADENGINE   required: { node: '&gt;=14.17' },<\/span>\r\n<span>npm WARN EBADENGINE   current: { node: 'v12.22.12', npm: '8.19.2' }<\/span>\r\n<span>npm WARN EBADENGINE }<\/span>\r\n<span><\/span><\/code><\/pre>\n<p>from Yarn:<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span>error typescript@5.1.1-rc: The engine &quot;node&quot; is incompatible with this module. Expected version &quot;&gt;=14.17&quot;. Got &quot;12.22.12&quot;<\/span>\r\n<span>error Found incompatible module.<\/span>\r\n<span><\/span><\/code><\/pre>\n<p><!-- or from pnpm --><\/p>\n<p><a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/53291\">See more information around this change here<\/a>.<\/p>\n<h3>Explicit <code>typeRoots<\/code> Disables Upward Walks for <code>node_modules\/@types<\/code><\/h3>\n<p>Previously, when the <code>typeRoots<\/code> option was specified in a <code>tsconfig.json<\/code> but resolution to any <code>typeRoots<\/code> directories had failed, TypeScript would still continue walking up parent directories, trying to resolve packages within each parent&#8217;s <code>node_modules\/@types<\/code> folder.<\/p>\n<p>This behavior could prompt excessive look-ups and has been disabled in TypeScript 5.1.\nAs a result, you may begin to see errors like the following based on entries in your <code>tsconfig.json<\/code>&#8216;s <code>types<\/code> option or <code>\/\/\/ &lt;reference &gt;<\/code> directives<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span>error TS2688: Cannot find type definition file for 'node'.<\/span>\r\n<span>error TS2688: Cannot find type definition file for 'mocha'.<\/span>\r\n<span>error TS2688: Cannot find type definition file for 'jasmine'.<\/span>\r\n<span>error TS2688: Cannot find type definition file for 'chai-http'.<\/span>\r\n<span>error TS2688: Cannot find type definition file for 'webpack-env&quot;'.<\/span>\r\n<span><\/span><\/code><\/pre>\n<p>The solution is typically to add specific entries for <code>node_modules\/@types<\/code> to your <code>typeRoots<\/code>:<\/p>\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><code><span>{<\/span>\r\n<span>    <\/span><span>&quot;compilerOptions&quot;<\/span><span>: {<\/span>\r\n<span>        <\/span><span>&quot;types&quot;<\/span><span>: [<\/span>\r\n<span>            <\/span><span>&quot;node&quot;<\/span><span>,<\/span>\r\n<span>            <\/span><span>&quot;mocha&quot;<\/span>\r\n<span>        ],<\/span>\r\n<span>        <\/span><span>&quot;typeRoots&quot;<\/span><span>: [<\/span>\r\n<span>            <\/span><span>\/\/ Keep whatever you had around before.<\/span>\r\n<span>            <\/span><span>&quot;.\/some-custom-types\/&quot;<\/span><span>,<\/span>\r\n\r\n<span>            <\/span><span>\/\/ You might need your local 'node_modules\/@types'.<\/span>\r\n<span>            <\/span><span>&quot;.\/node_modules\/@types&quot;<\/span><span>,<\/span>\r\n\r\n<span>            <\/span><span>\/\/ You might also need to specify a shared 'node_modules\/@types'<\/span>\r\n<span>            <\/span><span>\/\/ if you're using a &quot;monorepo&quot; layout.<\/span>\r\n<span>            <\/span><span>&quot;..\/..\/node_modules\/@types&quot;<\/span><span>,<\/span>\r\n<span>        ]<\/span>\r\n<span>    }<\/span>\r\n<span>}<\/span>\r\n<\/code><\/pre>\n<p>More information is available <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/51715\">on the original change on our issue tracker<\/a>.<\/p>\n<h2>What&#8217;s Next<\/h2>\n<p>At this point, we anticipate very few changes to TypeScript 5.1 apart from critical bug fixes and minor bug fixes on our language service.\nIn the next few weeks, we&#8217;ll be releasing a stable version of TypeScript 5.1.\n<a href=\"https:\/\/github.com\/microsoft\/TypeScript\/issues\/53031\">Keep an eye on our iteration plan<\/a> for target release dates and more if you need to plan around that.<\/p>\n<p>During this period, our team is also already working on TypeScript 5.2, and we&#8217;ve just made <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/issues\/54298\">the TypeScript 5.2 Iteration Plan<\/a> public as well.\nSimilarly, that describes our main focus areas, planned work, and target release dates which you can use to for your own plans.\nTo try out that upcoming work, you can <a href=\"https:\/\/www.typescriptlang.org\/docs\/handbook\/nightly-builds.html\">try a nightly build<\/a> of TypeScript.<\/p>\n<p>So give the RC or our nightlies a try, and we&#8217;d love to hear about anything you run into.<\/p>\n<p>Happy Hacking!<\/p>\n<p>&#8211; Daniel Rosenwasser and the TypeScript Team<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today we&#8217;re excited to announce our Release Candidate of TypeScript 5.1! Between now and the stable release of TypeScript 5.1, we expect no further changes apart from critical bug fixes. To get started using the RC, you can get it through NuGet, or through npm with the following command: npm install -D typescript@rc Here&#8217;s a [&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-3929","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-typescript"],"acf":[],"blog_post_summary":"<p>Today we&#8217;re excited to announce our Release Candidate of TypeScript 5.1! Between now and the stable release of TypeScript 5.1, we expect no further changes apart from critical bug fixes. To get started using the RC, you can get it through NuGet, or through npm with the following command: npm install -D typescript@rc Here&#8217;s a [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/3929","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=3929"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/3929\/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=3929"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/categories?post=3929"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/tags?post=3929"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}