{"id":2453,"date":"2020-02-20T14:59:07","date_gmt":"2020-02-20T22:59:07","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/typescript\/?p=2453"},"modified":"2020-04-15T11:17:52","modified_gmt":"2020-04-15T19:17:52","slug":"announcing-typescript-3-8","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-3-8\/","title":{"rendered":"Announcing TypeScript 3.8"},"content":{"rendered":"<p>Today we&#8217;re proud to release TypeScript 3.8!<\/p>\n<p>For those unfamiliar with TypeScript, it&#8217;s a language that adds syntax for types on top of JavaScript which can be analyzed through a process called <em>static type-checking<\/em>. This type-checking can tell us about errors like typos and values that are potentially <code>null<\/code> and <code>undefined<\/code> before we even run our code. More than just that, that same type analysis can be used to provide a solid editing experience for both TypeScript <em>and<\/em> JavaScript, powering operations like code completion, find-all-references, quick fixes, and refactorings. In fact, if you&#8217;re already using JavaScript in an editor like Visual Studio and Visual Studio Code, your editing experience is really being powered by TypeScript! So if you&#8217;re interested in learning more, <a href=\"https:\/\/www.typescriptlang.org\/\" rel=\"nofollow\">head over to our website<\/a>.<\/p>\n<p>If you&#8217;re already ready to use TypeScript, you can get it <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.TypeScript.MSBuild\" rel=\"nofollow\">through NuGet<\/a>, or use 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<\/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-382\" rel=\"nofollow\">Downloading for Visual Studio 2019\/2017<\/a><\/li>\n<li>Following <a href=\"https:\/\/code.visualstudio.com\/docs\/typescript\/typescript-compiling#_using-newer-typescript-versions\" rel=\"nofollow\">instructions for the latest Visual Studio Code<\/a>.<\/li>\n<li><a href=\"https:\/\/packagecontrol.io\/packages\/TypeScript\" rel=\"nofollow\">Sublime Text 3 via PackageControl<\/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-directory-watching\">Better Directory Watching on Linux and <code>watchOptions<\/code><\/a><\/li>\n<li><a href=\"#assume-direct-dependencies\">&#8220;Fast and Loose&#8221; Incremental Checking<\/a><\/li>\n<li>Editor Features\n<ul>\n<li><a href=\"#convert-to-template-string\">Convert to Template String<\/a><\/li>\n<li><a href=\"#call-hierarchy\">Call Hierarchy<\/a><\/li>\n<\/ul>\n<\/li>\n<li><a href=\"#breaking-changes\">Breaking Changes<\/a><\/li>\n<\/ul>\n<h2><span id=\"type-only-imports-exports\">Type-Only Imports and Exports<\/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 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 <a href=\"https:\/\/github.com\/microsoft\/TypeScript\/pull\/36092\/\">relevant changes<\/a> around broadening where imports from an <code>import type<\/code> declaration can be used.<\/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 at runtime, it acts entirely like a normal property and there&#8217;s no way to tell that it was declared with a <code>private<\/code> modifier. 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 also 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>One more thing to think about 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<p>A final consideration might be speed: <code>private<\/code> properties are no different from any other property, so accessing them is as fast as any other property access no matter which runtime you target. In contrast, because <code>#<\/code> private fields are downleveled using <code>WeakMap<\/code>s, they may be slower to use. While some runtimes might optimize their actual implementations of <code>#<\/code> private fields, and even have speedy <code>WeakMap<\/code> implementations, that might not be the case in all runtimes.<\/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 on Linux 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><span id=\"editor-features\">Editor Features<\/span><\/h2>\n<h3><span id=\"convert-to-template-string\">Convert to Template String<\/span><\/h3>\n<p>Thanks to <a href=\"https:\/\/github.com\/bigaru\">Arooran Thanabalasingam (bigaru)<\/a>, TypeScript 3.8 ships a new refactoring to convert string concatenations like<\/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: #a31515;\">\"I have \"<\/span> <span class=\"pl-c1\">+<\/span> <span class=\"pl-s1\">numApples<\/span> <span class=\"pl-c1\">+<\/span> <span style=\"color: #a31515;\">\" apples\"<\/span><\/pre>\n<\/div>\n<p>into template strings like the following.<\/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: #a31515;\">`I have <span class=\"pl-s1\"><span class=\"pl-kos\">${<\/span>numApples<span class=\"pl-kos\">}<\/span><\/span> apples`<\/span><\/pre>\n<\/div>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/typescript\/wp-content\/uploads\/sites\/11\/2020\/02\/convertToTemplateString-3.8.gif\" alt=\"Convert to template string in action\"\/><\/p>\n<h3><span id=\"call-hierarchy\">Call Hierarchy<\/span><\/h3>\n<p>It&#8217;s often useful to figure out who&#8217;s calling a given function. TypeScript has a way to find all references of a declaration (i.e. the <em>Find All References<\/em> command), and most people can use that to answer that question &#8211; but it can be slightly cumbersome. For example, imagine trying to find out who calls a function named <code>foo<\/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;\">export<\/span> <span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-en\">foo<\/span><span class=\"pl-kos\">(<\/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;\">\/\/ later, much farther away from 'foo'...<\/span>\r\n<span style=\"color: #0000ff;\">export<\/span> <span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-en\">bar<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-en\">foo<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/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\">baz<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-en\">foo<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>Once we find out that <code>foo<\/code> is called by <code>bar<\/code> and <code>baz<\/code>, we also want to know who calls <code>bar<\/code> and <code>baz<\/code> too! So we can invoke <em>Find All References<\/em> on <code>bar<\/code> and <code>baz<\/code> too, but that loses the context of who&#8217;s calling <code>foo<\/code>, the question we were originally trying to answer.<\/p>\n<p>To address the limitations here, some editors have a feature to visualize the ways a function will be called through a command called <em>Show Call Hierarchy<\/em>, and TypeScript 3.8 officially supports the <em>Call Hierarchy<\/em> feature.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/typescript\/wp-content\/uploads\/sites\/11\/2020\/02\/callHierarchy-3.8-still.png\" alt=\"A screenshot of call hierarchy\" \/><\/p>\n<p><em>Call Hierarchy<\/em> might be a bit confusing at first, and it takes a bit of usage to build up an intuition around it. Let&#8217;s consider the following 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;\">function<\/span> <span class=\"pl-en\">frequentlyCalledFunction<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span style=\"color: #148A14;\">\/\/ do something useful<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-en\">callerA<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-en\">frequentlyCalledFunction<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-en\">callerB<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-en\">callerA<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-en\">callerC<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-en\">frequentlyCalledFunction<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n\r\n<span style=\"color: #0000ff;\">function<\/span> <span class=\"pl-en\">entryPoint<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-en\">callerA<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-en\">callerB<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n    <span class=\"pl-en\">callerC<\/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>The following textual tree diagram shows the call hierarchy of <code>frequentlyCalledFunction<\/code>.<\/p>\n<pre><code>frequentlyCalledFunction\r\n \u2502\r\n \u251c\u2500callerA\r\n \u2502  \u251c\u2500 callerB\r\n \u2502  \u2502   \u2514\u2500 entryPoint\r\n \u2502  \u2502\r\n \u2502  \u2514\u2500 entryPoint\r\n \u2502\r\n \u2514\u2500 callerC\r\n     \u2514\u2500 entryPoint\r\n<\/code><\/pre>\n<p>Here we see that the immediate callers of <code>frequentlyCalledFunction<\/code> are <code>callerA<\/code> and <code>callerC<\/code>. If we want to know who calls <code>callerA<\/code>, we can see that our program&#8217;s <code>entryPoint<\/code> calls it directly, along with a function called <code>callerB<\/code>. We can further expand out the callers of <code>callerB<\/code> and <code>callerC<\/code> to see that they&#8217;re only called within the <code>entryPoint<\/code> function.<\/p>\n<p><em>Call Hierarchy<\/em> is already supported for TypeScript and JavaScript in <a href=\"https:\/\/code.visualstudio.com\/insiders\/\" rel=\"nofollow\">Visual Studio Code Insiders<\/a>, and will be available in the next stable version.<\/p>\n<p><a href=\"https:\/\/camo.githubusercontent.com\/7ebf7192831b3d43a46a9ee0a3354eed6c639d98\/68747470733a2f2f646576626c6f67732e6d6963726f736f66742e636f6d2f747970657363726970742f77702d636f6e74656e742f75706c6f6164732f73697465732f31312f323032302f30322f63616c6c4869657261726368792d332e382e676966\" target=\"_blank\" rel=\"noopener noreferrer\"><img decoding=\"async\" src=\"https:\/\/camo.githubusercontent.com\/7ebf7192831b3d43a46a9ee0a3354eed6c639d98\/68747470733a2f2f646576626c6f67732e6d6963726f736f66742e636f6d2f747970657363726970742f77702d636f6e74656e742f75706c6f6164732f73697465732f31312f323032302f30322f63616c6c4869657261726368792d332e382e676966\" alt=\"Call Hierarchy in action\" data-canonical-src=\"https:\/\/devblogs.microsoft.com\/typescript\/wp-content\/uploads\/sites\/11\/2020\/02\/callHierarchy-3.8.gif\" \/><\/a><\/p>\n<h2><span id=\"breaking-changes\">Breaking Changes<\/span><\/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>Optional Arguments with no Inferences are Correctly Marked as Implicitly <code>any<\/code><\/h3>\n<p>In the following code, <code>param<\/code> is now marked with an error under <code>noImplicitAny<\/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;\">function<\/span> <span class=\"pl-en\">foo<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">f<\/span>: <span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-c1\">=&gt;<\/span> <span class=\"pl-smi\"><span style=\"color: #0000ff;\">void<\/span><\/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 class=\"pl-en\">foo<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">param<\/span>?<span class=\"pl-kos\">)<\/span> <span class=\"pl-c1\">=&gt;<\/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><span class=\"pl-kos\">;<\/span><\/pre>\n<\/div>\n<p>This is because there is no corresponding parameter for the type of <code>f<\/code> in <code>foo<\/code>. This seems unlikely to be intentional, but it can be worked around by providing an explicit type for <code>param<\/code>.<\/p>\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: #0000ff;\">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>We anticipate that our next version, TypeScript 3.9, will be coming mid-May of 2020, and will mostly focus on performance, polish, and potentially smarter type-checking for <code>Promise<\/code>s. In the coming days our planning documents will be published to give an idea of specifics.<\/p>\n<p>But please don&#8217;t wait until 3.9 &#8211; 3.8 is a fantastic release with lots of great improvements, so grab it today!<\/p>\n<p>Have fun, and happy hacking!<\/p>\n<p>&#8211; Daniel Rosenwasser and the TypeScript Team<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today we&#8217;re proud to release TypeScript 3.8! For those unfamiliar with TypeScript, it&#8217;s a language that adds syntax for types on top of JavaScript which can be analyzed through a process called static type-checking. This type-checking can tell us about errors like typos and values that are potentially null and undefined before we even run [&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-2453","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-typescript"],"acf":[],"blog_post_summary":"<p>Today we&#8217;re proud to release TypeScript 3.8! For those unfamiliar with TypeScript, it&#8217;s a language that adds syntax for types on top of JavaScript which can be analyzed through a process called static type-checking. This type-checking can tell us about errors like typos and values that are potentially null and undefined before we even run [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/2453","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=2453"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/2453\/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=2453"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/categories?post=2453"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/tags?post=2453"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}