{"id":2432,"date":"2020-02-06T16:09:22","date_gmt":"2020-02-07T00:09:22","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/typescript\/?p=2432"},"modified":"2020-02-06T16:09:22","modified_gmt":"2020-02-07T00:09:22","slug":"announcing-typescript-3-8-rc","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-3-8-rc\/","title":{"rendered":"Announcing TypeScript 3.8 RC"},"content":{"rendered":"<p>Today we&#8217;re announcing the Release Candidate for TypeScript 3.8! Between this RC and our final release, we expect no 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\" rel=\"nofollow\">through NuGet<\/a>, or through npm with the following command:<\/p>\n<div class=\"highlight highlight-source-shell\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\">npm install typescript@rc<\/pre>\n<\/div>\n<p>You can also get editor support by<\/p>\n<ul>\n<li><a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=TypeScriptTeam.typescript-38rc\" rel=\"nofollow\">Downloading for Visual Studio 2019\/2017<\/a><\/li>\n<li>Using <a href=\"https:\/\/code.visualstudio.com\/insiders\/\" rel=\"nofollow\">Visual Studio Code Insiders<\/a> or following <a href=\"https:\/\/code.visualstudio.com\/docs\/typescript\/typescript-compiling#_using-newer-typescript-versions\">instructions for the latest Visual Studio Code<\/a>.<\/li>\n<li>Following directions for <a href=\"https:\/\/github.com\/Microsoft\/TypeScript-Sublime-Plugin\/#note-using-different-versions-of-typescript\">Sublime Text<\/a>.<\/li>\n<\/ul>\n<p>TypeScript 3.8 brings a lot of new features, including new or upcoming ECMAScript standards features, new syntax for importing\/exporting only types, and more.<\/p>\n<ul>\n<li><a href=\"#type-only-imports-exports\">Type-Only Imports and Exports<\/a><\/li>\n<li><a href=\"#ecmascript-private-fields\">ECMAScript Private Fields<\/a><\/li>\n<li><a href=\"#export-star-as-namespace-syntax\"><code>export * as ns<\/code> Syntax<\/a><\/li>\n<li><a href=\"#top-level-await\">Top-Level <code>await<\/code><\/a><\/li>\n<li><a href=\"#jsdoc-modifiers\">JSDoc Property Modifiers<\/a><\/li>\n<li><a href=\"#better-folder-watching\">Better Directory Watching and <code>watchOptions<\/code><\/a><\/li>\n<li><a href=\"#assume-direct-dependencies\">&#8220;Fast and Loose&#8221; Incremental Checking<\/a><\/li>\n<\/ul>\n<h2><span id=\"type-only-imports-exports\">Type-Only Imports and Export<\/span><\/h2>\n<p>This feature is something most users may never have to think about; however, if you&#8217;ve hit issues here, it might be of interest (especially when compiling under <code>--isolatedModules<\/code>, our <code>transpileModule<\/code> API, or Babel).<\/p>\n<p>TypeScript reuses JavaScript&#8217;s import syntax in order to let us reference types. For instance, in the following example, we&#8217;re able to import <code>doThing<\/code> which is a JavaScript value along with <code>Options<\/code> which is purely a TypeScript type.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #148A14;\">\/\/ .\/foo.ts<\/span>\r\n<span style=\"color: #0000ff;\">interface<\/span> <span style=\"color: #267F99;\">Options<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #148A14;\">\/\/ ...<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span style=\"color: #0000ff;\">export<\/span> <span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-en\">doThing<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">options<\/span>: <span style=\"color: #267F99;\">Options<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #148A14;\">\/\/ ...<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span style=\"color: #148A14;\">\/\/ .\/bar.ts<\/span>\r\n<span style=\"color: #0000ff;\">import<\/span> <span class=\"pl-kos\">{<\/span> <span class=\"pl-s1\">doThing<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #267F99;\">Options<\/span> <span class=\"pl-kos\">}<\/span> <span style=\"color: #0000ff;\">from<\/span> <span style=\"color: #a31515;\">\".\/foo.js\"<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-en\">doThingBetter<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">options<\/span>: <span style=\"color: #267F99;\">Options<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #148A14;\">\/\/ do something twice as good<\/span>\r\n    <span class=\"pl-en\">doThing<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">options<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-en\">doThing<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">options<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>This is convenient because <em>most of the time<\/em> we don&#8217;t have to worry about what&#8217;s being imported &#8211; just that we&#8217;re importing <em>something<\/em>.<\/p>\n<p>Unfortunately, this only worked because of a feature called <em>import elision<\/em>. When TypeScript outputs JavaScript files, it sees that <code>Options<\/code> is only used as a type, and it automatically drops its import. The resulting output looks kind of like this:<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #148A14;\">\/\/ .\/foo.js<\/span>\r\n<span style=\"color: #0000ff;\">export<\/span> <span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-en\">doThing<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">options<\/span>: <span class=\"pl-v\">Options<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #148A14;\">\/\/ ...<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span style=\"color: #148A14;\">\/\/ .\/bar.js<\/span>\r\n<span style=\"color: #0000ff;\">import<\/span> <span class=\"pl-kos\">{<\/span> <span class=\"pl-s1\">doThing<\/span> <span class=\"pl-kos\">}<\/span> <span style=\"color: #0000ff;\">from<\/span> <span style=\"color: #a31515;\">\".\/foo.js\"<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-en\">doThingBetter<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">options<\/span>: <span class=\"pl-v\">Options<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #148A14;\">\/\/ do something twice as good<\/span>\r\n    <span class=\"pl-en\">doThing<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">options<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-en\">doThing<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">options<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>Again, this behavior is usually great, but it causes some other problems.<\/p>\n<p>First of all, there are some places where it&#8217;s ambiguous whether a value or a type is being exported. For example, in the following example is <code>MyThing<\/code> a value or a type?<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #0000ff;\">import<\/span> <span class=\"pl-kos\">{<\/span> <span style=\"color: #267F99;\">MyThing<\/span> <span class=\"pl-kos\">}<\/span> <span style=\"color: #0000ff;\">from<\/span> <span style=\"color: #a31515;\">\".\/some-module.js\"<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #0000ff;\">export<\/span> <span class=\"pl-kos\">{<\/span> <span style=\"color: #267F99;\">MyThing<\/span> <span class=\"pl-kos\">}<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>Limiting ourselves to just this file, there&#8217;s no way to know. Both Babel and TypeScript&#8217;s <code>transpileModule<\/code> API will emit code that doesn&#8217;t work correctly if <code>MyThing<\/code> is only a type, and TypeScript&#8217;s <code>isolatedModules<\/code> flag will warn us that it&#8217;ll be a problem. The real problem here is that there&#8217;s no way to say &#8220;no, no, I really only meant the type &#8211; this should be erased&#8221;, so import elision isn&#8217;t good enough.<\/p>\n<p>The other issue was that TypeScript&#8217;s import elision would get rid of import statements that <em>only<\/em> contained imports used as types. That caused observably different behavior for modules that have side-effects, and so users would have to insert a <em>second<\/em> import statement purely to ensure side-effects.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #148A14;\">\/\/ This statement will get erased because of import elision.<\/span>\r\n<span style=\"color: #0000ff;\">import<\/span> <span class=\"pl-kos\">{<\/span> <span style=\"color: #267F99;\">SomeTypeFoo<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #267F99;\">SomeOtherTypeBar<\/span> <span class=\"pl-kos\">}<\/span> <span style=\"color: #0000ff;\">from<\/span> <span style=\"color: #a31515;\">\".\/module-with-side-effects\"<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #148A14;\">\/\/ This statement always sticks around.<\/span>\r\n<span style=\"color: #0000ff;\">import<\/span> <span style=\"color: #a31515;\">\".\/module-with-side-effects\"<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>A concrete place where we saw this coming up was in frameworks like Angular.js (1.x) where <a href=\"https:\/\/docs.angularjs.org\/guide\/services\" rel=\"nofollow\">services<\/a> needed to be registered globally (which is a side-effect), but where those services were only <code>import<\/code>ed for types.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #148A14;\">\/\/ .\/service.ts<\/span>\r\n<span style=\"color: #0000ff;\">export<\/span> <span style=\"color: #0000ff;\">class<\/span> <span style=\"color: #267F99;\">Service<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #148A14;\">\/\/ ...<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n<span class=\"pl-en\">register<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #a31515;\">\"globalServiceId\"<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #267F99;\">Service<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #148A14;\">\/\/ .\/consumer.ts<\/span>\r\n<span style=\"color: #0000ff;\">import<\/span> <span class=\"pl-kos\">{<\/span> <span style=\"color: #267F99;\">Service<\/span> <span class=\"pl-kos\">}<\/span> <span style=\"color: #0000ff;\">from<\/span> <span style=\"color: #a31515;\">\".\/service.js\"<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span class=\"pl-en\">inject<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #a31515;\">\"globalServiceId\"<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">service<\/span>: <span style=\"color: #267F99;\">Service<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #148A14;\">\/\/ do stuff with Service<\/span>\r\n<span class=\"pl-kos\">}<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>As a result, <code>.\/service.js<\/code> will never get run, and things will break at runtime.<\/p>\n<p>To avoid this class of issues, we realized we needed to give users more fine-grained control over how things were getting imported\/elided.<\/p>\n<p>As a solution in TypeScript 3.8, we&#8217;ve added a new syntax for type-only imports and exports.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #0000ff;\">import<\/span> <span style=\"color: #0000ff;\">type<\/span> <span class=\"pl-kos\">{<\/span> <span style=\"color: #267F99;\">SomeThing<\/span> <span class=\"pl-kos\">}<\/span> <span style=\"color: #0000ff;\">from<\/span> <span style=\"color: #a31515;\">\".\/some-module.js\"<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #0000ff;\">export<\/span> <span style=\"color: #0000ff;\">type<\/span> <span class=\"pl-kos\">{<\/span> <span style=\"color: #267F99;\">SomeThing<\/span> <span class=\"pl-kos\">}<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p><code>import type<\/code> only imports declarations to be used for type annotations and declarations. It <em>always<\/em> gets fully erased, so there&#8217;s no remnant of it at runtime. Similarly, <code>export type<\/code> only provides an export that can be used for type contexts, and is also erased from TypeScript&#8217;s output.<\/p>\n<p>It&#8217;s important to note that classes have a value at runtime and a type at design-time, and the use is very context-sensitive. When using <code>import type<\/code> to import a class, you can&#8217;t do things like extend from it.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #0000ff;\">import<\/span> <span style=\"color: #0000ff;\">type<\/span> <span class=\"pl-kos\">{<\/span> <span style=\"color: #267F99;\">Component<\/span> <span class=\"pl-kos\">}<\/span> <span style=\"color: #0000ff;\">from<\/span> <span style=\"color: #a31515;\">\"react\"<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #0000ff;\">interface<\/span> <span style=\"color: #267F99;\">ButtonProps<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #148A14;\">\/\/ ...<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span style=\"color: #0000ff;\">class<\/span> <span style=\"color: #267F99;\">Button<\/span> <span style=\"color: #0000ff;\">extends<\/span> <span style=\"color: #267F99;\">Component<\/span><span class=\"pl-kos\">&lt;<\/span><span style=\"color: #267F99;\">ButtonProps<\/span><span class=\"pl-kos\">&gt;<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #148A14;\">\/\/               ~~~~~~~~~<\/span>\r\n    <span style=\"color: #148A14;\">\/\/ error! 'Component' only refers to a type, but is being used as a value here.<\/span>\r\n\r\n    <span style=\"color: #148A14;\">\/\/ ...<\/span>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>If you&#8217;ve used Flow before, the syntax is fairly similar. One difference is that we&#8217;ve added a few restrictions to avoid code that might appear ambiguous.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #148A14;\">\/\/ Is only 'Foo' a type? Or every declaration in the import?<\/span>\r\n<span style=\"color: #148A14;\">\/\/ We just give an error because it's not clear.<\/span>\r\n\r\n<span style=\"color: #0000ff;\">import<\/span> <span style=\"color: #0000ff;\">type<\/span> <span style=\"color: #267F99;\">Foo<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-kos\">{<\/span> <span style=\"color: #267F99;\">Bar<\/span><span class=\"pl-kos\">,<\/span> <span style=\"color: #267F99;\">Baz<\/span> <span class=\"pl-kos\">}<\/span> <span style=\"color: #0000ff;\">from<\/span> <span style=\"color: #a31515;\">\"some-module\"<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #148A14;\">\/\/     ~~~~~~~~~~~~~~~~~~~~~~<\/span>\r\n<span style=\"color: #148A14;\">\/\/ error! A type-only import can specify a default import or named bindings, but not both.<\/span><\/pre>\n<\/div>\n<p>In conjunction with <code>import type<\/code>, we&#8217;ve also added a new compiler flag to control what happens with imports that won&#8217;t be utilized at runtime: <code>importsNotUsedAsValues<\/code>. This flag takes 3 different values:<\/p>\n<ul>\n<li><code>remove<\/code>: this is today&#8217;s behavior of dropping these imports. It&#8217;s going to continue to be the default, and is a non-breaking change.<\/li>\n<li><code>preserve<\/code>: this <em>preserves<\/em> all imports whose values are never used. This can cause imports\/side-effects to be preserved.<\/li>\n<li><code>error<\/code>: this preserves all imports (the same as the <code>preserve<\/code> option), but will error when a value import is only used as a type. This might be useful if you want to ensure no values are being accidentally imported, but still make side-effect imports explicit.<\/li>\n<\/ul>\n<p>For more information about the feature, you can <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/35200\">take a look at the pull request<\/a>, and some of the <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/36092\/\">relevant changes<\/a> that we&#8217;ve made since the beta release.<\/p>\n<h2><span id=\"ecmascript-private-fields\">ECMAScript Private Fields<\/span><\/h2>\n<p>TypeScript 3.8 brings support for ECMAScript&#8217;s private fields, part of the <a href=\"https:\/\/github.com\/tc39\/proposal-class-fields\/\">stage-3 class fields proposal<\/a>. This work was started and driven to completion by our good friends at Bloomberg!<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #0000ff;\">class<\/span> <span style=\"color: #267F99;\">Person<\/span> <span class=\"pl-kos\">{<\/span>\r\n    #<span class=\"pl-c1\">name<\/span>: <span style=\"color: #0000ff;\">string<\/span>\r\n\r\n    <span class=\"pl-en\">constructor<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">name<\/span>: <span style=\"color: #0000ff;\">string<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n        <span style=\"color: #0000ff;\">this<\/span><span class=\"pl-kos\">.<\/span>#<span class=\"pl-c1\">name<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">name<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-kos\">}<\/span>\r\n\r\n    <span class=\"pl-en\">greet<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n        <span class=\"pl-smi\">console<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">log<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #a31515;\">`Hello, my name is <span class=\"pl-s1\"><span class=\"pl-kos\">${<\/span><span style=\"color: #0000ff;\">this<\/span><span class=\"pl-kos\">.<\/span>#<span class=\"pl-c1\">name<\/span><span class=\"pl-kos\">}<\/span><\/span>!`<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-kos\">}<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span style=\"color: #0000ff;\">let<\/span> <span class=\"pl-s1\">jeremy<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #0000ff;\">new<\/span> <span style=\"color: #267F99;\">Person<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #a31515;\">\"Jeremy Bearimy\"<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span class=\"pl-s1\">jeremy<\/span><span class=\"pl-kos\">.<\/span>#<span class=\"pl-c1\">name<\/span>\r\n<span style=\"color: #148A14;\">\/\/     ~~~~~<\/span>\r\n<span style=\"color: #148A14;\">\/\/ Property '#name' is not accessible outside class 'Person'<\/span>\r\n<span style=\"color: #148A14;\">\/\/ because it has a private identifier.<\/span><\/pre>\n<\/div>\n<p>Unlike regular properties (even ones declared with the <code>private<\/code> modifier), private fields have a few rules to keep in mind. Some of them are:<\/p>\n<ul>\n<li>Private fields start with a <code>#<\/code> character. Sometimes we call these <em>private names<\/em>.<\/li>\n<li>Every private field name is uniquely scoped to its containing class.<\/li>\n<li>TypeScript accessibility modifiers like <code>public<\/code> or <code>private<\/code> can&#8217;t be used on private fields.<\/li>\n<li>Private fields can&#8217;t be accessed or even detected outside of the containing class &#8211; even by JS users! Sometimes we call this <em>hard privacy<\/em>.<\/li>\n<\/ul>\n<p>Apart from &#8220;hard&#8221; privacy, another benefit of private fields is that uniqueness we just mentioned. For example, regular property declarations are prone to being overwritten in subclasses.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #0000ff;\">class<\/span> <span style=\"color: #267F99;\">C<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-c1\">foo<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #09885A;\">10<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n    <span class=\"pl-en\">cHelper<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n        <span style=\"color: #0000ff;\">return<\/span> <span style=\"color: #0000ff;\">this<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">foo<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-kos\">}<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span style=\"color: #0000ff;\">class<\/span> <span style=\"color: #267F99;\">D<\/span> <span style=\"color: #0000ff;\">extends<\/span> <span style=\"color: #267F99;\">C<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-c1\">foo<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #09885A;\">20<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n    <span class=\"pl-en\">dHelper<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n        <span style=\"color: #0000ff;\">return<\/span> <span style=\"color: #0000ff;\">this<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">foo<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-kos\">}<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span style=\"color: #0000ff;\">let<\/span> <span class=\"pl-s1\">instance<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #0000ff;\">new<\/span> <span style=\"color: #267F99;\">D<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #148A14;\">\/\/ 'this.foo' refers to the same property on each instance.<\/span>\r\n<span class=\"pl-smi\">console<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">log<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">instance<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">cHelper<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span> <span style=\"color: #148A14;\">\/\/ prints '20'<\/span>\r\n<span class=\"pl-smi\">console<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">log<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">instance<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">dHelper<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span> <span style=\"color: #148A14;\">\/\/ prints '20'<\/span><\/pre>\n<\/div>\n<p>With private fields, you&#8217;ll never have to worry about this, since each field name is unique to the containing class.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #0000ff;\">class<\/span> <span style=\"color: #267F99;\">C<\/span> <span class=\"pl-kos\">{<\/span>\r\n    #<span class=\"pl-c1\">foo<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #09885A;\">10<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n    <span class=\"pl-en\">cHelper<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n        <span style=\"color: #0000ff;\">return<\/span> <span style=\"color: #0000ff;\">this<\/span><span class=\"pl-kos\">.<\/span>#<span class=\"pl-c1\">foo<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-kos\">}<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span style=\"color: #0000ff;\">class<\/span> <span style=\"color: #267F99;\">D<\/span> <span style=\"color: #0000ff;\">extends<\/span> <span style=\"color: #267F99;\">C<\/span> <span class=\"pl-kos\">{<\/span>\r\n    #<span class=\"pl-c1\">foo<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #09885A;\">20<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n    <span class=\"pl-en\">dHelper<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n        <span style=\"color: #0000ff;\">return<\/span> <span style=\"color: #0000ff;\">this<\/span><span class=\"pl-kos\">.<\/span>#<span class=\"pl-c1\">foo<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-kos\">}<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span style=\"color: #0000ff;\">let<\/span> <span class=\"pl-s1\">instance<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #0000ff;\">new<\/span> <span style=\"color: #267F99;\">D<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #148A14;\">\/\/ 'this.#foo' refers to a different field within each class.<\/span>\r\n<span class=\"pl-smi\">console<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">log<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">instance<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">cHelper<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span> <span style=\"color: #148A14;\">\/\/ prints '10'<\/span>\r\n<span class=\"pl-smi\">console<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">log<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">instance<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">dHelper<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span> <span style=\"color: #148A14;\">\/\/ prints '20'<\/span><\/pre>\n<\/div>\n<p>Another thing worth noting is that accessing a private field on any other type will result in a <code>TypeError<\/code>!<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #0000ff;\">class<\/span> <span style=\"color: #267F99;\">Square<\/span> <span class=\"pl-kos\">{<\/span>\r\n    #<span class=\"pl-c1\">sideLength<\/span>: <span style=\"color: #0000ff;\">number<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n    <span class=\"pl-en\">constructor<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">sideLength<\/span>: <span style=\"color: #0000ff;\">number<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n        <span style=\"color: #0000ff;\">this<\/span><span class=\"pl-kos\">.<\/span>#<span class=\"pl-c1\">sideLength<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">sideLength<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-kos\">}<\/span>\r\n\r\n    <span class=\"pl-en\">equals<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">other<\/span>: <span style=\"color: #0000ff;\">any<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n        <span style=\"color: #0000ff;\">return<\/span> <span style=\"color: #0000ff;\">this<\/span><span class=\"pl-kos\">.<\/span>#<span class=\"pl-c1\">sideLength<\/span> <span class=\"pl-c1\">===<\/span> <span class=\"pl-s1\">other<\/span><span class=\"pl-kos\">.<\/span>#<span class=\"pl-c1\">sideLength<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-kos\">}<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span style=\"color: #0000ff;\">const<\/span> <span class=\"pl-s1\">a<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #0000ff;\">new<\/span> <span style=\"color: #267F99;\">Square<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #09885A;\">100<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #0000ff;\">const<\/span> <span class=\"pl-s1\">b<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">{<\/span> <span class=\"pl-c1\">sideLength<\/span>: <span style=\"color: #09885A;\">100<\/span> <span class=\"pl-kos\">}<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #148A14;\">\/\/ Boom!<\/span>\r\n<span style=\"color: #148A14;\">\/\/ TypeError: attempted to get private field on non-instance<\/span>\r\n<span style=\"color: #148A14;\">\/\/ This fails because 'b' is not an instance of 'Square'.<\/span>\r\n<span class=\"pl-smi\">console<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">log<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">a<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">equals<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">b<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>Finally, for any plain <code>.js<\/code> file users, private fields <em>always<\/em> have to be declared before they&#8217;re assigned to.<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #0000ff;\">class<\/span> <span class=\"pl-v\">C<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #148A14;\">\/\/ No declaration for '#foo'<\/span>\r\n    <span style=\"color: #148A14;\">\/\/ :(<\/span>\r\n\r\n    <span class=\"pl-en\">constructor<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">foo<\/span>: <span class=\"pl-s1\">number<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n        <span style=\"color: #148A14;\">\/\/ SyntaxError!<\/span>\r\n        <span style=\"color: #148A14;\">\/\/ '#foo' needs to be declared before writing to it.<\/span>\r\n        <span style=\"color: #0000ff;\">this<\/span><span class=\"pl-kos\">.<\/span>#<span class=\"pl-c1\">foo<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">foo<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-kos\">}<\/span>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>JavaScript has always allowed users to access undeclared properties, whereas TypeScript has always required declarations for class properties. With private fields, declarations are always needed regardless of whether we&#8217;re working in <code>.js<\/code> or <code>.ts<\/code> files.<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #0000ff;\">class<\/span> <span class=\"pl-v\">C<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #148A14;\">\/** <span class=\"pl-k\">@type<\/span> {number} *\/<\/span>\r\n    #<span class=\"pl-c1\">foo<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n    <span class=\"pl-en\">constructor<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">foo<\/span>: <span class=\"pl-s1\">number<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n        <span style=\"color: #148A14;\">\/\/ This works.<\/span>\r\n        <span style=\"color: #0000ff;\">this<\/span><span class=\"pl-kos\">.<\/span>#<span class=\"pl-c1\">foo<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">foo<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-kos\">}<\/span>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>For more information about the implementation, you can <a href=\"https:\/\/github.com\/Microsoft\/TypeScript\/pull\/30829\">check out the original pull request<\/a><\/p>\n<h3>Which should I use?<\/h3>\n<p>We&#8217;ve already received many questions on which type of privates you should use as a TypeScript user: most commonly, &#8220;should I use the <code>private<\/code> keyword, or ECMAScript&#8217;s hash\/pound (<code>#<\/code>) private fields?&#8221;<\/p>\n<p>Like all good questions, the answer is not good: it depends!<\/p>\n<p>When it comes to properties, TypeScript&#8217;s <code>private<\/code> modifiers are fully erased &#8211; that means that while the data will be there, nothing is encoded in your JavaScript output about how the property was declared. At runtime, it acts entirely like a normal property. That means that when using the <code>private<\/code> keyword, privacy is only enforced at compile-time\/design-time, and for JavaScript consumers, it&#8217;s entirely intent-based.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #0000ff;\">class<\/span> <span style=\"color: #267F99;\">C<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #0000ff;\">private<\/span> <span class=\"pl-c1\">foo<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #09885A;\">10<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span style=\"color: #148A14;\">\/\/ This is an error at compile time,<\/span>\r\n<span style=\"color: #148A14;\">\/\/ but when TypeScript outputs .js files,<\/span>\r\n<span style=\"color: #148A14;\">\/\/ it'll run fine and print '10'.<\/span>\r\n<span class=\"pl-smi\">console<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">log<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #0000ff;\">new<\/span> <span style=\"color: #267F99;\">C<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">foo<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>    <span style=\"color: #148A14;\">\/\/ prints '10'<\/span>\r\n<span style=\"color: #148A14;\">\/\/                  ~~~<\/span>\r\n<span style=\"color: #148A14;\">\/\/ error! Property 'foo' is private and only accessible within class 'C'.<\/span>\r\n\r\n<span style=\"color: #148A14;\">\/\/ TypeScript allows this at compile-time<\/span>\r\n<span style=\"color: #148A14;\">\/\/ as a \"work-around\" to avoid the error.<\/span>\r\n<span class=\"pl-smi\">console<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">log<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #0000ff;\">new<\/span> <span style=\"color: #267F99;\">C<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">[<\/span><span style=\"color: #a31515;\">\"foo\"<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span> <span style=\"color: #148A14;\">\/\/ prints '10'<\/span><\/pre>\n<\/div>\n<p>The upside is that this sort of &#8220;soft privacy&#8221; can help your consumers temporarily work around not having access to some API, and works in any runtime.<\/p>\n<p>On the other hand, ECMAScript&#8217;s <code>#<\/code> privates are completely inaccessible outside of the class.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #0000ff;\">class<\/span> <span style=\"color: #267F99;\">C<\/span> <span class=\"pl-kos\">{<\/span>\r\n    #<span class=\"pl-c1\">foo<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #09885A;\">10<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span class=\"pl-smi\">console<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">log<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #0000ff;\">new<\/span> <span style=\"color: #267F99;\">C<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">.<\/span>#<span class=\"pl-c1\">foo<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span> <span style=\"color: #148A14;\">\/\/ SyntaxError<\/span>\r\n<span style=\"color: #148A14;\">\/\/                  ~~~~<\/span>\r\n<span style=\"color: #148A14;\">\/\/ TypeScript reports an error *and*<\/span>\r\n<span style=\"color: #148A14;\">\/\/ this won't work at runtime!<\/span>\r\n\r\n<span class=\"pl-smi\">console<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">log<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #0000ff;\">new<\/span> <span style=\"color: #267F99;\">C<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">[<\/span><span style=\"color: #a31515;\">\"#foo\"<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span> <span style=\"color: #148A14;\">\/\/ prints undefined<\/span>\r\n<span style=\"color: #148A14;\">\/\/          ~~~~~~~~~~~~~~~<\/span>\r\n<span style=\"color: #148A14;\">\/\/ TypeScript reports an error under 'noImplicitAny',<\/span>\r\n<span style=\"color: #148A14;\">\/\/ and this prints 'undefined'.<\/span><\/pre>\n<\/div>\n<p>This hard privacy is really useful for strictly ensuring that nobody can take use of any of your internals. If you&#8217;re a library author, removing or renaming a private field should never cause a breaking change.<\/p>\n<p>As we mentioned, another benefit is that subclassing can be easier with ECMAScript&#8217;s <code>#<\/code> privates because they <em>really<\/em> are private. When using ECMAScript <code>#<\/code> private fields, no subclass ever has to worry about collisions in field naming. When it comes to TypeScript&#8217;s <code>private<\/code> property declarations, users still have to be careful not to trample over properties declared in superclasses.<\/p>\n<p>Finally, something to consider is where you intend for your code to run. TypeScript currently can&#8217;t support this feature unless targeting ECMAScript 2015 (ES6) targets or higher. This is because our downleveled implementation uses <code>WeakMap<\/code>s to enforce privacy, and <code>WeakMap<\/code>s can&#8217;t be polyfilled in a way that doesn&#8217;t cause memory leaks. In contrast, TypeScript&#8217;s <code>private<\/code>-declared properties work with all targets &#8211; even ECMAScript 3!<\/p>\n<h3>Kudos!<\/h3>\n<p>It&#8217;s worth reiterating how much work went into this feature from our contributors at Bloomberg. They were diligent in taking the time to learn to contribute features to the compiler\/language service, and paid close attention to the ECMAScript specification to test that the feature was implemented in compliant manner. They even improved another 3rd party project, <a href=\"https:\/\/github.com\/cla-assistant\/cla-assistant\/pull\/410\">CLA Assistant<\/a>, which made contributing to TypeScript even easier.<\/p>\n<p>We&#8217;d like to extend a special thanks to:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/joeywatts\">Joey Watts<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/mheiber\">Max Heiber<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/robpalme\">Rob Palmer<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/Neuroboy23\">Michael Gunter<\/a><\/li>\n<li>Ravi Amin<\/li>\n<li><a href=\"https:\/\/github.com\/jbhoosreddy\">Jaideep Bhoosreddy<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/molisani\">Michael Molisani<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/tim-mc\">Tim McClure<\/a><\/li>\n<\/ul>\n<h2><span id=\"export-star-as-namespace-syntax\"><code>export * as ns<\/code> Syntax<\/span><\/h2>\n<p>It&#8217;s often common to have a single entry-point that exposes all the members of another module as a single member.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #0000ff;\">import<\/span> * <span style=\"color: #0000ff;\">as<\/span> <span class=\"pl-s1\">utilities<\/span> <span style=\"color: #0000ff;\">from<\/span> <span style=\"color: #a31515;\">\".\/utilities.js\"<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #0000ff;\">export<\/span> <span class=\"pl-kos\">{<\/span> <span class=\"pl-s1\">utilities<\/span> <span class=\"pl-kos\">}<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>This is so common that ECMAScript 2020 recently added a new syntax to support this pattern!<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #0000ff;\">export<\/span> * <span style=\"color: #0000ff;\">as<\/span> <span class=\"pl-s1\">utilities<\/span> <span style=\"color: #0000ff;\">from<\/span> <span style=\"color: #a31515;\">\".\/utilities.js\"<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>This is a nice quality-of-life improvement to JavaScript, and TypeScript 3.8 implements this syntax. When your module target is earlier than <code>es2020<\/code>, TypeScript will output something along the lines of the first code snippet.<\/p>\n<p>Special thanks to community member <a href=\"https:\/\/github.com\/Kingwl\">Wenlu Wang (Kingwl)<\/a> who implemented this feature! For more information, <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/34903\">check out the original pull request<\/a>.<\/p>\n<h2><span id=\"top-level-await\">Top-Level <code>await<\/code><\/span><\/h2>\n<p>Most modern environments that provide I\/O in JavaScript (like HTTP requests) is asynchronous, and many modern APIs return <code>Promise<\/code>s. While this has a lot of benefits in making operations non-blocking, it makes certain things like loading files or external content surprisingly tedious.<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span class=\"pl-en\">fetch<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #a31515;\">\"...\"<\/span><span class=\"pl-kos\">)<\/span>\r\n    <span class=\"pl-kos\">.<\/span><span class=\"pl-en\">then<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">response<\/span> <span class=\"pl-c1\">=&gt;<\/span> <span class=\"pl-s1\">response<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">text<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">)<\/span>\r\n    <span class=\"pl-kos\">.<\/span><span class=\"pl-en\">then<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">greeting<\/span> <span class=\"pl-c1\">=&gt;<\/span> <span class=\"pl-kos\">{<\/span> <span class=\"pl-smi\">console<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">log<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">greeting<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">}<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>To avoid <code>.then<\/code> chains with <code>Promise<\/code>s, JavaScript users often introduced an <code>async<\/code> function in order to use <code>await<\/code>, and then immediately called the function after defining it.<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #0000ff;\">async<\/span> <span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-en\">main<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #0000ff;\">const<\/span> <span class=\"pl-s1\">response<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #0000ff;\">await<\/span> <span class=\"pl-en\">fetch<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #a31515;\">\"...\"<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span style=\"color: #0000ff;\">const<\/span> <span class=\"pl-s1\">greeting<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #0000ff;\">await<\/span> <span class=\"pl-s1\">response<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">text<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-smi\">console<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">log<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">greeting<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span class=\"pl-en\">main<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span>\r\n    <span class=\"pl-kos\">.<\/span><span class=\"pl-en\">catch<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">e<\/span> <span class=\"pl-c1\">=&gt;<\/span> <span class=\"pl-smi\">console<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">error<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">e<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">)<\/span><\/pre>\n<\/div>\n<p>To avoid introducing an <code>async<\/code> function, we can use a handy upcoming ECMAScript feature called &#8220;top-level <code>await<\/code>&#8220;.<\/p>\n<p>Previously in JavaScript (along with most other languages with a similar feature), <code>await<\/code> was only allowed within the body of an <code>async<\/code> function. However, with top-level <code>await<\/code>, we can use <code>await<\/code> at the top level of a module.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #0000ff;\">const<\/span> <span class=\"pl-s1\">response<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #0000ff;\">await<\/span> <span class=\"pl-en\">fetch<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #a31515;\">\"...\"<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #0000ff;\">const<\/span> <span class=\"pl-s1\">greeting<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #0000ff;\">await<\/span> <span class=\"pl-s1\">response<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">text<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-smi\">console<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">log<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">greeting<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span style=\"color: #148A14;\">\/\/ Make sure we're a module<\/span>\r\n<span style=\"color: #0000ff;\">export<\/span> <span class=\"pl-kos\">{<\/span><span class=\"pl-kos\">}<\/span><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>Note there&#8217;s a subtlety: top-level <code>await<\/code> only works at the top level of a <em>module<\/em>, and files are only considered modules when TypeScript finds an <code>import<\/code> or an <code>export<\/code>. In some basic cases, you might need to write out <code>export {}<\/code> as some boilerplate to make sure of this.<\/p>\n<p>Top level <code>await<\/code> may not work in all environments where you might expect at this point. Currently, you can only use top level <code>await<\/code> when the <code>target<\/code> compiler option is <code>es2017<\/code> or above, and <code>module<\/code> is <code>esnext<\/code> or <code>system<\/code>. Support within several environments and bundlers may be limited or may require enabling experimental support.<\/p>\n<p>For more information on our implementation, you can <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/35813\">check out the original pull request<\/a>.<\/p>\n<h2><span id=\"es2020-for-target-and-module\"><code>es2020<\/code> for <code>target<\/code> and <code>module<\/code><\/span><\/h2>\n<p>Thanks to <a href=\"https:\/\/github.com\/saschanaz\">Kagami Sascha Rosylight (saschanaz)<\/a>, TypeScript 3.8 supports <code>es2020<\/code> as an option for <code>module<\/code> and <code>target<\/code>. This will preserve newer ECMAScript 2020 features like optional chaining, nullish coalescing, <code>export * as ns<\/code>, and dynamic <code>import(...)<\/code> syntax. It also means <code>bigint<\/code> literals now have a stable <code>target<\/code> below <code>esnext<\/code>.<\/p>\n<h2><span id=\"jsdoc-modifiers\">JSDoc Property Modifiers<\/span><\/h2>\n<p>TypeScript 3.8 supports JavaScript files by turning on the <code>allowJs<\/code> flag, and also supports <em>type-checking<\/em> those JavaScript files via the <code>checkJs<\/code> option or by adding a <code>\/\/ @ts-check<\/code> comment to the top of your <code>.js<\/code> files.<\/p>\n<p>Because JavaScript files don&#8217;t have dedicated syntax for type-checking, TypeScript leverages JSDoc. TypeScript 3.8 understands a few new JSDoc tags for properties.<\/p>\n<p>First are the accessibility modifiers: <code>@public<\/code>, <code>@private<\/code>, and <code>@protected<\/code>. These tags work exactly like <code>public<\/code>, <code>private<\/code>, and <code>protected<\/code> respectively work in TypeScript.<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #148A14;\">\/\/ <span class=\"pl-k\">@ts<\/span>-check<\/span>\r\n\r\n<span style=\"color: #0000ff;\">class<\/span> <span class=\"pl-v\">Foo<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-en\">constructor<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n        <span style=\"color: #148A14;\">\/** <span class=\"pl-k\">@private<\/span> *\/<\/span>\r\n        <span style=\"color: #0000ff;\">this<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">stuff<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #09885A;\">100<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-kos\">}<\/span>\r\n\r\n    <span class=\"pl-en\">printStuff<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n        <span class=\"pl-smi\">console<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">log<\/span><span class=\"pl-kos\">(<\/span><span style=\"color: #0000ff;\">this<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">stuff<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-kos\">}<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span style=\"color: #0000ff;\">new<\/span> <span class=\"pl-v\">Foo<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">stuff<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #148A14;\">\/\/        ~~~~~<\/span>\r\n<span style=\"color: #148A14;\">\/\/ error! Property 'stuff' is private and only accessible within class 'Foo'.<\/span><\/pre>\n<\/div>\n<ul>\n<li><code>@public<\/code> is always implied and can be left off, but means that a property can be reached from anywhere.<\/li>\n<li><code>@private<\/code> means that a property can only be used within the containing class.<\/li>\n<li><code>@protected<\/code> means that a property can only be used within the containing class, and all derived subclasses, but not on dissimilar instances of the containing class.<\/li>\n<\/ul>\n<p>Next, we&#8217;ve also added the <code>@readonly<\/code> modifier to ensure that a property is only ever written to during initialization.<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #148A14;\">\/\/ <span class=\"pl-k\">@ts<\/span>-check<\/span>\r\n\r\n<span style=\"color: #0000ff;\">class<\/span> <span class=\"pl-v\">Foo<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-en\">constructor<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n        <span style=\"color: #148A14;\">\/** <span class=\"pl-k\">@readonly<\/span> *\/<\/span>\r\n        <span style=\"color: #0000ff;\">this<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">stuff<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #09885A;\">100<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-kos\">}<\/span>\r\n\r\n    <span class=\"pl-en\">writeToStuff<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n        <span style=\"color: #0000ff;\">this<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">stuff<\/span> <span class=\"pl-c1\">=<\/span> <span style=\"color: #09885A;\">200<\/span><span class=\"pl-kos\">;<\/span>\r\n        <span style=\"color: #148A14;\">\/\/   ~~~~~<\/span>\r\n        <span style=\"color: #148A14;\">\/\/ Cannot assign to 'stuff' because it is a read-only property.<\/span>\r\n    <span class=\"pl-kos\">}<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span style=\"color: #0000ff;\">new<\/span> <span class=\"pl-v\">Foo<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">stuff<\/span><span class=\"pl-c1\">++<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #148A14;\">\/\/        ~~~~~<\/span>\r\n<span style=\"color: #148A14;\">\/\/ Cannot assign to 'stuff' because it is a read-only property.<\/span><\/pre>\n<\/div>\n<h2><span id=\"better-directory-watching\">Better Directory Watching and <code>watchOptions<\/code><\/span><\/h2>\n<p>TypeScript 3.8 ships a new strategy for watching directories, which is crucial for efficiently picking up changes to <code>node_modules<\/code>.<\/p>\n<p>For some context, on operating systems like Linux, TypeScript installs directory watchers (as opposed to file watchers) on <code>node_modules<\/code> and many of its subdirectories to detect changes in dependencies. This is because the number of available file watchers is often eclipsed by the of files in <code>node_modules<\/code>, whereas there are way fewer directories to track.<\/p>\n<p>Older versions of TypeScript would <em>immediately<\/em> install directory watchers on folders, and at startup that would be fine; however, during an npm install, a lot of activity will take place within <code>node_modules<\/code> and that can overwhelm TypeScript, often slowing editor sessions to a crawl. To prevent this, TypeScript 3.8 waits slightly before installing directory watchers to give these highly volatile directories some time to stabilize.<\/p>\n<p>Because every project might work better under different strategies, and this new approach might not work well for your workflows, TypeScript 3.8 introduces a new <code>watchOptions<\/code> field in <code>tsconfig.json<\/code> and <code>jsconfig.json<\/code> which allows users to tell the compiler\/language service which watching strategies should be used to keep track of files and directories.<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #148A14;\">\/\/ Some typical compiler options<\/span>\r\n    <span style=\"color: #a31515;\">\"compilerOptions\"<\/span>: <span class=\"pl-kos\">{<\/span>\r\n        <span style=\"color: #a31515;\">\"target\"<\/span>: <span style=\"color: #a31515;\">\"es2020\"<\/span><span class=\"pl-kos\">,<\/span>\r\n        <span style=\"color: #a31515;\">\"moduleResolution\"<\/span>: <span style=\"color: #a31515;\">\"node\"<\/span><span class=\"pl-kos\">,<\/span>\r\n        <span style=\"color: #148A14;\">\/\/ ...<\/span>\r\n    <span class=\"pl-kos\">}<\/span><span class=\"pl-kos\">,<\/span>\r\n\r\n    <span style=\"color: #148A14;\">\/\/ NEW: Options for file\/directory watching<\/span>\r\n    <span style=\"color: #a31515;\">\"watchOptions\"<\/span>: <span class=\"pl-kos\">{<\/span>\r\n        <span style=\"color: #148A14;\">\/\/ Use native file system events for files and directories<\/span>\r\n        <span style=\"color: #a31515;\">\"watchFile\"<\/span>: <span style=\"color: #a31515;\">\"useFsEvents\"<\/span><span class=\"pl-kos\">,<\/span>\r\n        <span style=\"color: #a31515;\">\"watchDirectory\"<\/span>: <span style=\"color: #a31515;\">\"useFsEvents\"<\/span><span class=\"pl-kos\">,<\/span>\r\n\r\n        <span style=\"color: #148A14;\">\/\/ Poll files for updates more frequently<\/span>\r\n        <span style=\"color: #148A14;\">\/\/ when they're updated a lot.<\/span>\r\n        <span style=\"color: #a31515;\">\"fallbackPolling\"<\/span>: <span style=\"color: #a31515;\">\"dynamicPriority\"<\/span>\r\n    <span class=\"pl-kos\">}<\/span>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p><code>watchOptions<\/code> contains 4 new options that can be configured:<\/p>\n<ul>\n<li><code>watchFile<\/code>: the strategy for how individual files are watched. This can be set to\n<ul>\n<li><code>fixedPollingInterval<\/code>: Check every file for changes several times a second at a fixed interval.<\/li>\n<li><code>priorityPollingInterval<\/code>: Check every file for changes several times a second, but use heuristics to check certain types of files less frequently than others.<\/li>\n<li><code>dynamicPriorityPolling<\/code>: Use a dynamic queue where less-frequently modified files will be checked less often.<\/li>\n<li><code>useFsEvents<\/code> (the default): Attempt to use the operating system\/file system&#8217;s native events for file changes.<\/li>\n<li><code>useFsEventsOnParentDirectory<\/code>: Attempt to use the operating system\/file system&#8217;s native events to listen for changes on a file&#8217;s containing directories. This can use fewer file watchers, but might be less accurate.<\/li>\n<\/ul>\n<\/li>\n<li><code>watchDirectory<\/code>: the strategy for how entire directory trees are watched under systems that lack recursive file-watching functionality. This can be set to:\n<ul>\n<li><code>fixedPollingInterval<\/code>: Check every directory for changes several times a second at a fixed interval.<\/li>\n<li><code>dynamicPriorityPolling<\/code>: Use a dynamic queue where less-frequently modified directories will be checked less often.<\/li>\n<li><code>useFsEvents<\/code> (the default): Attempt to use the operating system\/file system&#8217;s native events for directory changes.<\/li>\n<\/ul>\n<\/li>\n<li><code>fallbackPolling<\/code>: when using file system events, this option specifies the polling strategy that gets used when the system runs out of native file watchers and\/or doesn&#8217;t support native file watchers. This can be set to\n<ul>\n<li><code>fixedPollingInterval<\/code>: <em>(See above.)<\/em><\/li>\n<li><code>priorityPollingInterval<\/code>: <em>(See above.)<\/em><\/li>\n<li><code>dynamicPriorityPolling<\/code>: <em>(See above.)<\/em><\/li>\n<\/ul>\n<\/li>\n<li><code>synchronousWatchDirectory<\/code>: Disable deferred watching on directories. Deferred watching is useful when lots of file changes might occur at once (e.g. a change in <code>node_modules<\/code> from running <code>npm install<\/code>), but you might want to disable it with this flag for some less-common setups.<\/li>\n<\/ul>\n<p>For more information on these changes, <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/35615\">head over to GitHub to see the pull request<\/a> to read more.<\/p>\n<h2><span id=\"assume-direct-dependencies\">&#8220;Fast and Loose&#8221; Incremental Checking<\/span><\/h2>\n<p>TypeScript&#8217;s <code>--watch<\/code> mode and <code>--incremental<\/code> mode can help tighten the feedback loop for projects. Turning on <code>--incremental<\/code> mode makes TypeScript keep track of which files can affect others, and on top of doing that, <code>--watch<\/code> mode keeps the compiler process open and reuses as much information in memory as possible.<\/p>\n<p>However, for much larger projects, even the dramatic gains in speed that these options afford us isn&#8217;t enough. For example, the Visual Studio Code team had built their own build tool around TypeScript called <code>gulp-tsb<\/code> which would be less accurate in assessing which files needed to be rechecked\/rebuilt in its watch mode, and as a result, could provide drastically low build times.<\/p>\n<p>Sacrificing accuracy for build speed, for better or worse, is a tradeoff many are willing to make in the TypeScript\/JavaScript world. Lots of users prioritize tightening their iteration time over addressing the errors up-front. As an example, it&#8217;s fairly common to build code regardless of the results of type-checking or linting.<\/p>\n<p>TypeScript 3.8 introduces a new compiler option called <code>assumeChangesOnlyAffectDirectDependencies<\/code>. When this option is enabled, TypeScript will avoid rechecking\/rebuilding all truly possibly-affected files, and only recheck\/rebuild files that have changed as well as files that directly import them.<\/p>\n<p>For example, consider a file <code>fileD.ts<\/code> that imports <code>fileC.ts<\/code> that imports <code>fileB.ts<\/code> that imports <code>fileA.ts<\/code> as follows:<\/p>\n<pre><code>fileA.ts &lt;- fileB.ts &lt;- fileC.ts &lt;- fileD.ts\r\n<\/code><\/pre>\n<p>In <code>--watch<\/code> mode, a change in <code>fileA.ts<\/code> would typically mean that TypeScript would need to at least re-check <code>fileB.ts<\/code>, <code>fileC.ts<\/code>, and <code>fileD.ts<\/code>. Under <code>assumeChangesOnlyAffectDirectDependencies<\/code>, a change in <code>fileA.ts<\/code> means that only <code>fileA.ts<\/code> and <code>fileB.ts<\/code> need to be re-checked.<\/p>\n<p>In a codebase like Visual Studio Code, this reduced rebuild times for changes in certain files from about 14 seconds to about 1 second. While we don&#8217;t necessarily recommend this option for all codebases, you might be interested if you have an extremely large codebase and are willing to defer full project errors until later (e.g. a dedicated build via a <code>tsconfig.fullbuild.json<\/code> or in CI).<\/p>\n<p>For more details, you can <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/35711\">see the original pull request<\/a>.<\/p>\n<h2>Breaking Changes<\/h2>\n<p>TypeScript 3.8 contains a few minor breaking changes that should be noted.<\/p>\n<h3>Stricter Assignability Checks to Unions with Index Signatures<\/h3>\n<p>Previously, excess properties were unchecked when assigning to unions where <em>any<\/em> type had an index signature &#8211; even if that excess property could <em>never<\/em> satisfy that index signature. In TypeScript 3.8, the type-checker is stricter, and only &#8220;exempts&#8221; properties from excess property checks if that property could plausibly satisfy an index signature.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #0000ff;\">const<\/span> <span class=\"pl-s1\">obj1<\/span>: <span class=\"pl-kos\">{<\/span> <span class=\"pl-kos\">[<\/span><span class=\"pl-s1\">x<\/span>: <span style=\"color: #0000ff;\">string<\/span><span class=\"pl-kos\">]<\/span>: <span style=\"color: #0000ff;\">number<\/span> <span class=\"pl-kos\">}<\/span> | <span class=\"pl-kos\">{<\/span> <span class=\"pl-c1\">a<\/span>: <span style=\"color: #0000ff;\">number<\/span> <span class=\"pl-kos\">}<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span class=\"pl-s1\">obj1<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">{<\/span> <span class=\"pl-c1\">a<\/span>: <span style=\"color: #09885A;\">5<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-c1\">c<\/span>: <span style=\"color: #a31515;\">'abc'<\/span> <span class=\"pl-kos\">}<\/span>\r\n<span style=\"color: #148A14;\">\/\/             ~<\/span>\r\n<span style=\"color: #148A14;\">\/\/ Error!<\/span>\r\n<span style=\"color: #148A14;\">\/\/ The type '{ [x: string]: number }' no longer exempts 'c'<\/span>\r\n<span style=\"color: #148A14;\">\/\/ from excess property checks on '{ a: number }'.<\/span>\r\n\r\n<span style=\"color: #0000ff;\">let<\/span> <span class=\"pl-s1\">obj2<\/span>: <span class=\"pl-kos\">{<\/span> <span class=\"pl-kos\">[<\/span><span class=\"pl-s1\">x<\/span>: <span style=\"color: #0000ff;\">string<\/span><span class=\"pl-kos\">]<\/span>: <span style=\"color: #0000ff;\">number<\/span> <span class=\"pl-kos\">}<\/span> | <span class=\"pl-kos\">{<\/span> <span class=\"pl-kos\">[<\/span><span class=\"pl-s1\">x<\/span>: <span style=\"color: #0000ff;\">number<\/span><span class=\"pl-kos\">]<\/span>: <span style=\"color: #0000ff;\">number<\/span> <span class=\"pl-kos\">}<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n<span class=\"pl-s1\">obj2<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">{<\/span> <span class=\"pl-c1\">a<\/span>: <span style=\"color: #a31515;\">'abc'<\/span> <span class=\"pl-kos\">}<\/span><span class=\"pl-kos\">;<\/span>\r\n<span style=\"color: #148A14;\">\/\/       ~<\/span>\r\n<span style=\"color: #148A14;\">\/\/ Error!<\/span>\r\n<span style=\"color: #148A14;\">\/\/ The types '{ [x: string]: number }' and '{ [x: number]: number }' no longer exempts 'a'<\/span>\r\n<span style=\"color: #148A14;\">\/\/ from excess property checks against '{ [x: number]: number }',<\/span>\r\n<span style=\"color: #148A14;\">\/\/ and it *is* sort of an excess property because 'a' isn't a numeric property name.<\/span>\r\n<span style=\"color: #148A14;\">\/\/ This one is more subtle.<\/span><\/pre>\n<\/div>\n<h3><code>object<\/code> in JSDoc is No Longer <code>any<\/code> Under <code>noImplicitAny<\/code><\/h3>\n<p>Historically, TypeScript&#8217;s support for checking JavaScript has been lax in certain ways in order to provide an approachable experience.<\/p>\n<p>For example, users often used <code>Object<\/code> in JSDoc to mean, &#8220;some object, I dunno what&#8221;, we&#8217;ve treated it as <code>any<\/code>.<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #148A14;\">\/\/ <span class=\"pl-k\">@ts<\/span>-check<\/span>\r\n\r\n<span style=\"color: #148A14;\">\/**<\/span>\r\n<span style=\"color: #148A14;\"> * <span class=\"pl-k\">@param<\/span> thing {<span style=\"color: #267F99;\">Object<\/span>} some object, i dunno what<\/span>\r\n<span style=\"color: #148A14;\"> *\/<\/span>\r\n<span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-en\">doSomething<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">thing<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #0000ff;\">let<\/span> <span class=\"pl-s1\">x<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">thing<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">x<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span style=\"color: #0000ff;\">let<\/span> <span class=\"pl-s1\">y<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">thing<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">y<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-s1\">thing<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>This is because treating it as TypeScript&#8217;s <code>Object<\/code> type would end up in code reporting uninteresting errors, since the <code>Object<\/code> type is an extremely vague type with few capabilities other than methods like <code>toString<\/code> and <code>valueOf<\/code>.<\/p>\n<p>However, TypeScript <em>does<\/em> have a more useful type named <code>object<\/code> (notice that lowercase <code>o<\/code>). The <code>object<\/code> type is more restrictive than <code>Object<\/code>, in that it rejects all primitive types like <code>string<\/code>, <code>boolean<\/code>, and <code>number<\/code>. Unfortunately, both <code>Object<\/code> and <code>object<\/code> were treated as <code>any<\/code> in JSDoc.<\/p>\n<p>Because <code>object<\/code> can come in handy and is used significantly less than <code>Object<\/code> in JSDoc, we&#8217;ve removed the special-case behavior in JavaScript files when using <code>noImplicitAny<\/code> so that in JSDoc, the <code>object<\/code> type really refers to the non-primitive <code>object<\/code> type.<\/p>\n<h2>What&#8217;s Next?<\/h2>\n<p>As you can see on <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/issues\/34898\">our current Iteration Plan<\/a>, the final release of TypeScript 3.8 is only a few weeks out, but it&#8217;s crucial that we get feedback about the RC before we release. As editor features we&#8217;ve developed become more mature, we&#8217;ll also show off functionality like Call Hierarchy and the &#8220;convert to template string&#8221; refactoring (which you can try now in <a href=\"https:\/\/code.visualstudio.com\/insiders\/\" rel=\"nofollow\">Visual Studio Code Insiders<\/a>). We would love it if you and your team could give it a try today and file an issue if you run into anything.<\/p>\n<p>So download the RC today! And happy hacking!<\/p>\n<p>&#8211; Daniel Rosenwasser and the TypeScript Team<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today we&#8217;re announcing the Release Candidate for TypeScript 3.8! Between this RC and our final release, we expect no 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 typescript@rc You can also get editor support by Downloading [&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-2432","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-typescript"],"acf":[],"blog_post_summary":"<p>Today we&#8217;re announcing the Release Candidate for TypeScript 3.8! Between this RC and our final release, we expect no 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 typescript@rc You can also get editor support by Downloading [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/2432","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=2432"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/2432\/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=2432"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/categories?post=2432"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/tags?post=2432"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}