(window.webpackJsonp=window.webpackJsonp||[]).push([[133],{858:function(t,s,a){"use strict";a.r(s);var e=a(20),n=Object(e.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"typescript-3-8"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#typescript-3-8"}},[t._v("#")]),t._v(" TypeScript 3.8")]),t._v(" "),a("ul",[a("li",[a("a",{attrs:{href:"#type-only-imports-exports"}},[t._v("Type-Only Imports and Exports")])]),t._v(" "),a("li",[a("a",{attrs:{href:"#ecmascript-private-fields"}},[t._v("ECMAScript Private Fields")])]),t._v(" "),a("li",[a("a",{attrs:{href:"#export-star-as-namespace-syntax"}},[a("code",[t._v("export * as ns")]),t._v("  Syntax")])]),t._v(" "),a("li",[a("a",{attrs:{href:"#top-level-await"}},[t._v("Top-Level  "),a("code",[t._v("await")])])]),t._v(" "),a("li",[a("a",{attrs:{href:"#jsdoc-modifiers"}},[t._v("JSDoc Property Modifiers")])]),t._v(" "),a("li",[a("a",{attrs:{href:"#better-directory-watching"}},[t._v("Better Directory Watching on Linux and  "),a("code",[t._v("watchOptions")])])]),t._v(" "),a("li",[a("a",{attrs:{href:"#assume-direct-dependencies"}},[t._v('"Fast and Loose" Incremental Checking')])])]),t._v(" "),a("h2",{attrs:{id:"类型导入和导出-type-only-imports-and-exports"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#类型导入和导出-type-only-imports-and-exports"}},[t._v("#")]),t._v(" "),a("span",{attrs:{id:"type-only-imports-exports"}}),t._v(" 类型导入和导出（Type-Only Imports and Exports）")]),t._v(" "),a("p",[t._v("This feature is something most users may never have to think about; however, if you've hit issues under  "),a("code",[t._v("--isolatedModules")]),t._v(" , TypeScript's  "),a("code",[t._v("transpileModule")]),t._v("  API, or Babel, this feature might be relevant.")]),t._v(" "),a("p",[t._v("TypeScript 3.8 adds a new syntax for type-only imports and exports.")]),t._v(" "),a("div",{staticClass:"language-ts extra-class"},[a("pre",{pre:!0,attrs:{class:"language-ts"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" SomeThing "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'./some-module.js'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("export")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" SomeThing "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[a("code",[t._v("import type")]),t._v("  only imports declarations to be used for type annotations and declarations.\nIt "),a("em",[t._v("always")]),t._v(" gets fully erased, so there's no remnant of it at runtime.\nSimilarly,  "),a("code",[t._v("export type")]),t._v("  only provides an export that can be used for type contexts, and is also erased from TypeScript's output.")]),t._v(" "),a("p",[t._v("It's important to note that classes have a value at runtime and a type at design-time, and the use is context-sensitive.\nWhen using  "),a("code",[t._v("import type")]),t._v("  to import a class, you can't do things like extend from it.")]),t._v(" "),a("div",{staticClass:"language-ts extra-class"},[a("pre",{pre:!0,attrs:{class:"language-ts"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" Component "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'react'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ButtonProps")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Button")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Component"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("ButtonProps"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//               ~~~~~~~~~")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// error! 'Component' only refers to a type, but is being used as a value here.")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("If you've used Flow before, the syntax is fairly similar.\nOne difference is that we've added a few restrictions to avoid code that might appear ambiguous.")]),t._v(" "),a("div",{staticClass:"language-ts extra-class"},[a("pre",{pre:!0,attrs:{class:"language-ts"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Is only 'Foo' a type? Or every declaration in the import?")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// We just give an error because it's not clear.")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Foo")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" Bar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Baz "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'some-module'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//     ~~~~~~~~~~~~~~~~~~~~~~")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// error! A type-only import can specify a default import or named bindings, but not both.")]),t._v("\n")])])]),a("p",[t._v("In conjunction with  "),a("code",[t._v("import type")]),t._v(" , TypeScript 3.8 also adds a new compiler flag to control what happens with imports that won't be utilized at runtime:  "),a("code",[t._v("importsNotUsedAsValues")]),t._v(" .\nThis flag takes 3 different values:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("remove")]),t._v(" : this is today's behavior of dropping these imports. It's going to continue to be the default, and is a non-breaking change.")]),t._v(" "),a("li",[a("code",[t._v("preserve")]),t._v(" : this "),a("em",[t._v("preserves")]),t._v(" all imports whose values are never used. This can cause imports/side-effects to be preserved.")]),t._v(" "),a("li",[a("code",[t._v("error")]),t._v(" : this preserves all imports (the same as the  "),a("code",[t._v("preserve")]),t._v("  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.")])]),t._v(" "),a("p",[t._v("For more information about the feature, you can "),a("a",{attrs:{href:"https://github.com/microsoft/TypeScript/pull/35200",target:"_blank",rel:"noopener noreferrer"}},[t._v("take a look at the pull request"),a("OutboundLink")],1),t._v(", and "),a("a",{attrs:{href:"https://github.com/microsoft/TypeScript/pull/36092/",target:"_blank",rel:"noopener noreferrer"}},[t._v("relevant changes"),a("OutboundLink")],1),t._v(" around broadening where imports from an  "),a("code",[t._v("import type")]),t._v("  declaration can be used.")]),t._v(" "),a("h2",{attrs:{id:"ecmascript-私有变量-ecmascript-private-fields"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#ecmascript-私有变量-ecmascript-private-fields"}},[t._v("#")]),t._v(" "),a("span",{attrs:{id:"ecmascript-private-fields"}}),t._v(" ECMAScript 私有变量（ECMAScript Private Fields")]),t._v(" "),a("p",[t._v("TypeScript 3.8 brings support for ECMAScript's private fields, part of the "),a("a",{attrs:{href:"https://github.com/tc39/proposal-class-fields/",target:"_blank",rel:"noopener noreferrer"}},[t._v("stage-3 class fields proposal"),a("OutboundLink")],1),t._v(".")]),t._v(" "),a("div",{staticClass:"language-ts extra-class"},[a("pre",{pre:!0,attrs:{class:"language-ts"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Person")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n  #name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n  "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constructor")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("#name "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n  "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("greet")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("console")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("log")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token template-string"}},[a("span",{pre:!0,attrs:{class:"token template-punctuation string"}},[t._v("`")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("Hello, my name is ")]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token interpolation-punctuation punctuation"}},[t._v("${")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("#name"),a("span",{pre:!0,attrs:{class:"token interpolation-punctuation punctuation"}},[t._v("}")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token template-punctuation string"}},[t._v("`")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" jeremy "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Person")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'Jeremy Bearimy'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\njeremy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("#name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//     ~~~~~")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Property '#name' is not accessible outside class 'Person'")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// because it has a private identifier.")]),t._v("\n")])])]),a("p",[t._v("Unlike regular properties (even ones declared with the  "),a("code",[t._v("private")]),t._v("  modifier), private fields have a few rules to keep in mind.\nSome of them are:")]),t._v(" "),a("ul",[a("li",[t._v("Private fields start with a  "),a("code",[t._v("#")]),t._v("  character. Sometimes we call these "),a("em",[t._v("private names")]),t._v(".")]),t._v(" "),a("li",[t._v("Every private field name is uniquely scoped to its containing class.")]),t._v(" "),a("li",[t._v("TypeScript accessibility modifiers like  "),a("code",[t._v("public")]),t._v("  or  "),a("code",[t._v("private")]),t._v("  can't be used on private fields.")]),t._v(" "),a("li",[t._v("Private fields can't be accessed or even detected outside of the containing class - even by JS users! Sometimes we call this "),a("em",[t._v("hard privacy")]),t._v(".")])]),t._v(" "),a("p",[t._v('Apart from "hard" privacy, another benefit of private fields is that uniqueness we just mentioned.\nFor example, regular property declarations are prone to being overwritten in subclasses.')]),t._v(" "),a("div",{staticClass:"language-ts extra-class"},[a("pre",{pre:!0,attrs:{class:"language-ts"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("C")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n  foo "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n  "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("cHelper")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("foo"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("D")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("C")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n  foo "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("20")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n  "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("dHelper")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("foo"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" instance "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("D")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 'this.foo' refers to the same property on each instance.")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("console")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("log")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("instance"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("cHelper")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// prints '20'")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("console")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("log")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("instance"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("dHelper")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// prints '20'")]),t._v("\n")])])]),a("p",[t._v("With private fields, you'll never have to worry about this, since each field name is unique to the containing class.")]),t._v(" "),a("div",{staticClass:"language-ts extra-class"},[a("pre",{pre:!0,attrs:{class:"language-ts"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("C")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n  #foo "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n  "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("cHelper")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("#foo"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("D")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("C")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n  #foo "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("20")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n  "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("dHelper")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("#foo"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" instance "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("D")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 'this.#foo' refers to a different field within each class.")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("console")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("log")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("instance"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("cHelper")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// prints '10'")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("console")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("log")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("instance"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("dHelper")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// prints '20'")]),t._v("\n")])])]),a("p",[t._v("Another thing worth noting is that accessing a private field on any other type will result in a  "),a("code",[t._v("TypeError")]),t._v(" !")]),t._v(" "),a("div",{staticClass:"language-ts extra-class"},[a("pre",{pre:!0,attrs:{class:"language-ts"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Square")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n  #sideLength"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("number")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n  "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constructor")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sideLength"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("number")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("#sideLength "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" sideLength"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n  "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("equals")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("other"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("#sideLength "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("===")]),t._v(" other"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("#sideLength"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Square")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" b "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" sideLength"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Boom!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// TypeError: attempted to get private field on non-instance")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// This fails because 'b' is not an instance of 'Square'.")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("console")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("log")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("equals")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("Finally, for any plain  "),a("code",[t._v(".js")]),t._v("  file users, private fields "),a("em",[t._v("always")]),t._v(" have to be declared before they're assigned to.")]),t._v(" "),a("div",{staticClass:"language-js extra-class"},[a("pre",{pre:!0,attrs:{class:"language-js"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("C")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// No declaration for '#foo'")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// :(")]),t._v("\n\n  "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("constructor")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("foo"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" number")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// SyntaxError!")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// '#foo' needs to be declared before writing to it.")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("#foo "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" foo"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("JavaScript has always allowed users to access undeclared properties, whereas TypeScript has always required declarations for class properties.\nWith private fields, declarations are always needed regardless of whether we're working in  "),a("code",[t._v(".js")]),t._v("  or  "),a("code",[t._v(".ts")]),t._v("  files.")]),t._v(" "),a("div",{staticClass:"language-js extra-class"},[a("pre",{pre:!0,attrs:{class:"language-js"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("C")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/** @type {number} */")]),t._v("\n  #foo"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n  "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("constructor")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("foo"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" number")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// This works.")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("#foo "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" foo"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("For more information about the implementation, you can "),a("a",{attrs:{href:"https://github.com/Microsoft/TypeScript/pull/30829",target:"_blank",rel:"noopener noreferrer"}},[t._v("check out the original pull request"),a("OutboundLink")],1)]),t._v(" "),a("h3",{attrs:{id:"which-should-i-use"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#which-should-i-use"}},[t._v("#")]),t._v(" Which should I use?")]),t._v(" "),a("p",[t._v("We've already received many questions on which type of privates you should use as a TypeScript user: most commonly, \"should I use the  "),a("code",[t._v("private")]),t._v("  keyword, or ECMAScript's hash/pound ( "),a("code",[t._v("#")]),t._v(' ) private fields?"\nIt depends!')]),t._v(" "),a("p",[t._v("When it comes to properties, TypeScript's  "),a("code",[t._v("private")]),t._v("  modifiers are fully erased - that means that at runtime, it acts entirely like a normal property and there's no way to tell that it was declared with a  "),a("code",[t._v("private modifier. When using the")]),t._v(" private` keyword, privacy is only enforced at compile-time/design-time, and for JavaScript consumers it's entirely intent-based.")]),t._v(" "),a("div",{staticClass:"language-ts extra-class"},[a("pre",{pre:!0,attrs:{class:"language-ts"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("C")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" foo "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// This is an error at compile time,")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// but when TypeScript outputs .js files,")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// it'll run fine and print '10'.")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("console")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("log")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("C")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("foo"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// prints '10'")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//                  ~~~")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// error! Property 'foo' is private and only accessible within class 'C'.")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// TypeScript allows this at compile-time")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// as a "work-around" to avoid the error.')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("console")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("log")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("C")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'foo'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// prints '10'")]),t._v("\n")])])]),a("p",[t._v('The upside is that this sort of "soft privacy" can help your consumers temporarily work around not having access to some API, and also works in any runtime.')]),t._v(" "),a("p",[t._v("On the other hand, ECMAScript's  "),a("code",[t._v("#")]),t._v("  privates are completely inaccessible outside of the class.")]),t._v(" "),a("div",{staticClass:"language-ts extra-class"},[a("pre",{pre:!0,attrs:{class:"language-ts"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("C")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n  #foo "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("console")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("log")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("C")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("#foo"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// SyntaxError")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//                  ~~~~")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// TypeScript reports an error *and*")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// this won't work at runtime!")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("console")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("log")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("C")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'#foo'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// prints undefined")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//          ~~~~~~~~~~~~~~~")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// TypeScript reports an error under 'noImplicitAny',")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// and this prints 'undefined'.")]),t._v("\n")])])]),a("p",[t._v("This hard privacy is really useful for strictly ensuring that nobody can take use of any of your internals.\nIf you're a library author, removing or renaming a private field should never cause a breaking change.")]),t._v(" "),a("p",[t._v("As we mentioned, another benefit is that subclassing can be easier with ECMAScript's  "),a("code",[t._v("#")]),t._v("  privates because they "),a("em",[t._v("really")]),t._v(" are private.\nWhen using ECMAScript  "),a("code",[t._v("#")]),t._v("  private fields, no subclass ever has to worry about collisions in field naming.\nWhen it comes to TypeScript's  "),a("code",[t._v("private")]),t._v("  property declarations, users still have to be careful not to trample over properties declared in superclasses.")]),t._v(" "),a("p",[t._v("One more thing to think about is where you intend for your code to run.\nTypeScript currently can't support this feature unless targeting ECMAScript 2015 (ES6) targets or higher.\nThis is because our downleveled implementation uses  "),a("code",[t._v("WeakMap")]),t._v(" s to enforce privacy, and  "),a("code",[t._v("WeakMap")]),t._v(" s can't be polyfilled in a way that doesn't cause memory leaks.\nIn contrast, TypeScript's  "),a("code",[t._v("private")]),t._v(" -declared properties work with all targets - even ECMAScript 3!")]),t._v(" "),a("p",[t._v("A final consideration might be speed:  "),a("code",[t._v("private")]),t._v("  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.\nIn contrast, because  "),a("code",[t._v("#")]),t._v("  private fields are downleveled using  "),a("code",[t._v("WeakMap")]),t._v(" s, they may be slower to use.\nWhile some runtimes might optimize their actual implementations of  "),a("code",[t._v("#")]),t._v("  private fields, and even have speedy  "),a("code",[t._v("WeakMap")]),t._v("  implementations, that might not be the case in all runtimes.")]),t._v(" "),a("h2",{attrs:{id:"export-as-ns-syntax"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#export-as-ns-syntax"}},[t._v("#")]),t._v(" "),a("span",{attrs:{id:"export-star-as-namespace-syntax"}}),t._v(" "),a("code",[t._v("export * as ns")]),t._v("  Syntax")]),t._v(" "),a("p",[t._v("It's often common to have a single entry-point that exposes all the members of another module as a single member.")]),t._v(" "),a("div",{staticClass:"language-ts extra-class"},[a("pre",{pre:!0,attrs:{class:"language-ts"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("as")]),t._v(" utilities "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'./utilities.js'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("export")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" utilities "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("This is so common that ECMAScript 2020 recently added a new syntax to support this pattern!")]),t._v(" "),a("div",{staticClass:"language-ts extra-class"},[a("pre",{pre:!0,attrs:{class:"language-ts"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("export")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("as")]),t._v(" utilities "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'./utilities.js'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("This is a nice quality-of-life improvement to JavaScript, and TypeScript 3.8 implements this syntax.\nWhen your module target is earlier than  "),a("code",[t._v("es2020")]),t._v(" , TypeScript will output something along the lines of the first code snippet.")]),t._v(" "),a("h2",{attrs:{id:"顶层-await-top-level-await"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#顶层-await-top-level-await"}},[t._v("#")]),t._v(" "),a("span",{attrs:{id:"top-level-await"}}),t._v(" 顶层 await（Top-Level await）")]),t._v(" "),a("p",[t._v('TypeScript 3.8 provides support for a handy upcoming ECMAScript feature called "top-level  '),a("code",[t._v("await")]),t._v(' ".')]),t._v(" "),a("p",[t._v("JavaScript users often introduce an  "),a("code",[t._v("async")]),t._v("  function in order to use  "),a("code",[t._v("await")]),t._v(" , and then immediately called the function after defining it.")]),t._v(" "),a("div",{staticClass:"language-js extra-class"},[a("pre",{pre:!0,attrs:{class:"language-js"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" response "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("fetch")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'...'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" greeting "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("text")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n  console"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("log")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("greeting"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("catch")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token parameter"}},[t._v("e")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" console"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("This is because previously in JavaScript (along with most other languages with a similar feature),  "),a("code",[t._v("await")]),t._v("  was only allowed within the body of an  "),a("code",[t._v("async")]),t._v("  function.\nHowever, with top-level  "),a("code",[t._v("await")]),t._v(" , we can use  "),a("code",[t._v("await")]),t._v("  at the top level of a module.")]),t._v(" "),a("div",{staticClass:"language-ts extra-class"},[a("pre",{pre:!0,attrs:{class:"language-ts"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" response "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("fetch")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'...'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" greeting "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("text")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("console")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("log")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("greeting"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Make sure we're a module")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("export")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("Note there's a subtlety: top-level  "),a("code",[t._v("await")]),t._v("  only works at the top level of a "),a("em",[t._v("module")]),t._v(", and files are only considered modules when TypeScript finds an  "),a("code",[t._v("import")]),t._v("  or an  "),a("code",[t._v("export")]),t._v(" .\nIn some basic cases, you might need to write out  "),a("code",[t._v("export {}")]),t._v("  as some boilerplate to make sure of this.")]),t._v(" "),a("p",[t._v("Top level  "),a("code",[t._v("await")]),t._v("  may not work in all environments where you might expect at this point.\nCurrently, you can only use top level  "),a("code",[t._v("await")]),t._v("  when the  "),a("code",[t._v("target")]),t._v("  compiler option is  "),a("code",[t._v("es2017")]),t._v("  or above, and  "),a("code",[t._v("module")]),t._v("  is  "),a("code",[t._v("esnext")]),t._v("  or  "),a("code",[t._v("system")]),t._v(" .\nSupport within several environments and bundlers may be limited or may require enabling experimental support.")]),t._v(" "),a("p",[t._v("For more information on our implementation, you can "),a("a",{attrs:{href:"https://github.com/microsoft/TypeScript/pull/35813",target:"_blank",rel:"noopener noreferrer"}},[t._v("check out the original pull request"),a("OutboundLink")],1),t._v(".")]),t._v(" "),a("h2",{attrs:{id:"es2020-for-target-and-module"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#es2020-for-target-and-module"}},[t._v("#")]),t._v(" "),a("span",{attrs:{id:"es2020-for-target-and-module"}}),t._v(" "),a("code",[t._v("es2020")]),t._v("  for  "),a("code",[t._v("target")]),t._v("  and  "),a("code",[t._v("module")])]),t._v(" "),a("p",[t._v("TypeScript 3.8 supports  "),a("code",[t._v("es2020")]),t._v("  as an option for  "),a("code",[t._v("module")]),t._v("  and  "),a("code",[t._v("target")]),t._v(" .\nThis will preserve newer ECMAScript 2020 features like optional chaining, nullish coalescing,  "),a("code",[t._v("export * as ns")]),t._v(" , and dynamic  "),a("code",[t._v("import(...)")]),t._v("  syntax.\nIt also means  "),a("code",[t._v("bigint")]),t._v("  literals now have a stable  "),a("code",[t._v("target")]),t._v("  below  "),a("code",[t._v("esnext")]),t._v(" .")]),t._v(" "),a("h2",{attrs:{id:"jsdoc-属性修饰词-jsdoc-property-modifiers"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#jsdoc-属性修饰词-jsdoc-property-modifiers"}},[t._v("#")]),t._v(" "),a("span",{attrs:{id:"jsdoc-modifiers"}}),t._v(" JSDoc 属性修饰词 (JSDoc Property Modifiers)")]),t._v(" "),a("p",[t._v("TypeScript 3.8 supports JavaScript files by turning on the  "),a("code",[t._v("allowJs")]),t._v("  flag, and also supports "),a("em",[t._v("type-checking")]),t._v(" those JavaScript files via the  "),a("code",[t._v("checkJs")]),t._v("  option or by adding a  "),a("code",[t._v("// @ts-check")]),t._v("  comment to the top of your  "),a("code",[t._v(".js")]),t._v("  files.")]),t._v(" "),a("p",[t._v("Because JavaScript files don't have dedicated syntax for type-checking, TypeScript leverages JSDoc.\nTypeScript 3.8 understands a few new JSDoc tags for properties.")]),t._v(" "),a("p",[t._v("First are the accessibility modifiers:  "),a("code",[t._v("@public")]),t._v(" ,  "),a("code",[t._v("@private")]),t._v(" , and  "),a("code",[t._v("@protected")]),t._v(" .\nThese tags work exactly like  "),a("code",[t._v("public")]),t._v(" ,  "),a("code",[t._v("private")]),t._v(" , and  "),a("code",[t._v("protected")]),t._v("  respectively work in TypeScript.")]),t._v(" "),a("div",{staticClass:"language-js extra-class"},[a("pre",{pre:!0,attrs:{class:"language-js"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// @ts-check")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Foo")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("constructor")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/** @private */")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("stuff "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n  "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("printStuff")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n    console"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("log")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("stuff"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Foo")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("stuff"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//        ~~~~~")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// error! Property 'stuff' is private and only accessible within class 'Foo'.")]),t._v("\n")])])]),a("ul",[a("li",[a("code",[t._v("@public")]),t._v("  是默认的，可以省略，它代表了一个属性可以从任何地方访问它")]),t._v(" "),a("li",[a("code",[t._v("@private")]),t._v("  表示一个属性只能在包含的类中访问")]),t._v(" "),a("li",[a("code",[t._v("@protected")]),t._v("  表示该属性只能在所包含的类及子类中访问，但不能在类的实例中访问")])]),t._v(" "),a("p",[t._v("下一步，我们计划添加  "),a("code",[t._v("@readonly")]),t._v("  修饰符，来确保一个属性只能在初始化时被修改：")]),t._v(" "),a("div",{staticClass:"language-js extra-class"},[a("pre",{pre:!0,attrs:{class:"language-js"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// @ts-check")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Foo")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("constructor")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/** @readonly */")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("stuff "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n  "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("writeToStuff")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("stuff "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("200")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//   ~~~~~")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Cannot assign to 'stuff' because it is a read-only property.")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Foo")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("stuff"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//        ~~~~~")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Cannot assign to 'stuff' because it is a read-only property.")]),t._v("\n")])])]),a("h2",{attrs:{id:"better-directory-watching-on-linux-and-watchoptions"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#better-directory-watching-on-linux-and-watchoptions"}},[t._v("#")]),t._v(" "),a("span",{attrs:{id:"better-directory-watching"}}),t._v(" Better Directory Watching on Linux and  "),a("code",[t._v("watchOptions")])]),t._v(" "),a("p",[t._v("TypeScript 3.8 ships a new strategy for watching directories, which is crucial for efficiently picking up changes to  "),a("code",[t._v("node_modules")]),t._v(" .")]),t._v(" "),a("p",[t._v("For some context, on operating systems like Linux, TypeScript installs directory watchers (as opposed to file watchers) on  "),a("code",[t._v("node_modules")]),t._v("  and many of its subdirectories to detect changes in dependencies.\nThis is because the number of available file watchers is often eclipsed by the of files in  "),a("code",[t._v("node_modules")]),t._v(" , whereas there are way fewer directories to track.")]),t._v(" "),a("p",[t._v("Older versions of TypeScript would "),a("em",[t._v("immediately")]),t._v(" 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  "),a("code",[t._v("node_modules")]),t._v("  and that can overwhelm TypeScript, often slowing editor sessions to a crawl.\nTo prevent this, TypeScript 3.8 waits slightly before installing directory watchers to give these highly volatile directories some time to stabilize.")]),t._v(" "),a("p",[t._v("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  "),a("code",[t._v("watchOptions")]),t._v("  field in  "),a("code",[t._v("tsconfig.json")]),t._v("  and  "),a("code",[t._v("jsconfig.json")]),t._v("  which allows users to tell the compiler/language service which watching strategies should be used to keep track of files and directories.")]),t._v(" "),a("div",{staticClass:"language-json5 extra-class"},[a("pre",{pre:!0,attrs:{class:"language-json5"}},[a("code",[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Some typical compiler options")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token property unquoted"}},[t._v("compilerOptions")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token property unquoted"}},[t._v("target")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'es2020'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token property unquoted"}},[t._v("moduleResolution")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'node'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n  "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// NEW: Options for file/directory watching")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token property unquoted"}},[t._v("watchOptions")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use native file system events for files and directories")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token property unquoted"}},[t._v("watchFile")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'useFsEvents'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token property unquoted"}},[t._v("watchDirectory")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'useFsEvents'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n    "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Poll files for updates more frequently")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// when they're updated a lot.")]),t._v("\n    "),a("span",{pre:!0,attrs:{class:"token property unquoted"}},[t._v("fallbackPolling")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'dynamicPriority'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n  "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[a("code",[t._v("watchOptions")]),t._v("  包含四种新的选项:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("watchFile")]),t._v(" : 监听单个文件的策略，它可以有以下值\n"),a("ul",[a("li",[a("code",[t._v("fixedPollingInterval")]),t._v(" : 以固定的时间间隔，检查文件的更改")]),t._v(" "),a("li",[a("code",[t._v("priorityPollingInterval")]),t._v(" : 以固定的时间间隔，检查文件的更改，但是使用「heuristics」检查某些类型的文件的频率比其他文件低（heuristics 怎么翻？）")]),t._v(" "),a("li",[a("code",[t._v("dynamicPriorityPolling")]),t._v(" : 使用动态队列，在该队列中，较少检查不经常修改的文件")]),t._v(" "),a("li",[a("code",[t._v("useFsEvents")]),t._v("  （默认）: 尝试使用操作系统 / 文件系统原生事件来监听文件更改")]),t._v(" "),a("li",[a("code",[t._v("useFsEventsOnParentDirectory")]),t._v(" : 尝试使用操作系统 / 文件系统原生事件来监听文件、目录的更改，这样可以使用较小的文件监听程序，但是准确性可能较低")])])]),t._v(" "),a("li",[a("code",[t._v("watchDirectory")]),t._v(" : 在缺少递归文件监听功能的系统中，使用哪种策略监听整个目录树，它可以有以下值 :\n"),a("ul",[a("li",[a("code",[t._v("fixedPollingInterval")]),t._v(" : 以固定的时间间隔，检查目录树的更改")]),t._v(" "),a("li",[a("code",[t._v("dynamicPriorityPolling")]),t._v(" : 使用动态队列，在该队列中，较少检查不经常修改的目录")]),t._v(" "),a("li",[a("code",[t._v("useFsEvents")]),t._v("  （默认）: 尝试使用操作系统 / 文件系统原生事件来监听目录更改")])])]),t._v(" "),a("li",[a("code",[t._v("fallbackPolling")]),t._v(" : 当使用文件系统的事件，该选项用来指定使用特定策略，它可以有以下值\n"),a("ul",[a("li",[a("code",[t._v("fixedPollingInterval")]),t._v(" : "),a("em",[t._v("(同上)")])]),t._v(" "),a("li",[a("code",[t._v("priorityPollingInterval")]),t._v(" : "),a("em",[t._v("(同上)")])]),t._v(" "),a("li",[a("code",[t._v("dynamicPriorityPolling")]),t._v(" : "),a("em",[t._v("(同上)")])])])]),t._v(" "),a("li",[a("code",[t._v("synchronousWatchDirectory")]),t._v(" : 在目录上禁用延迟监听功能。在可能一次发生大量文件（如  "),a("code",[t._v("node_modules")]),t._v(" ）更改时，它非常有用，但是你可能需要一些不太常见的设置时，禁用它。")])]),t._v(" "),a("p",[t._v("For more information on these changes, "),a("a",{attrs:{href:"https://github.com/microsoft/TypeScript/pull/35615",target:"_blank",rel:"noopener noreferrer"}},[t._v("head over to GitHub to see the pull request"),a("OutboundLink")],1),t._v(" to read more.")]),t._v(" "),a("h2",{attrs:{id:"fast-and-loose-incremental-checking"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#fast-and-loose-incremental-checking"}},[t._v("#")]),t._v(" "),a("span",{attrs:{id:"assume-direct-dependencies"}}),t._v(' "Fast and Loose" Incremental Checking')]),t._v(" "),a("p",[t._v("TypeScript 3.8 introduces a new compiler option called  "),a("code",[t._v("assumeChangesOnlyAffectDirectDependencies")]),t._v(" .\nWhen 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.")]),t._v(" "),a("p",[t._v("For example, consider a file  "),a("code",[t._v("fileD.ts")]),t._v("  that imports  "),a("code",[t._v("fileC.ts")]),t._v("  that imports  "),a("code",[t._v("fileB.ts")]),t._v("  that imports  "),a("code",[t._v("fileA.ts")]),t._v("  as follows:")]),t._v(" "),a("div",{staticClass:"language-txt extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v("fileA.ts <- fileB.ts <- fileC.ts <- fileD.ts\n")])])]),a("p",[t._v("In  "),a("code",[t._v("--watch")]),t._v("  mode, a change in  "),a("code",[t._v("fileA.ts")]),t._v("  would typically mean that TypeScript would need to at least re-check  "),a("code",[t._v("fileB.ts")]),t._v(" ,  "),a("code",[t._v("fileC.ts")]),t._v(" , and  "),a("code",[t._v("fileD.ts")]),t._v(" .\nUnder  "),a("code",[t._v("assumeChangesOnlyAffectDirectDependencies")]),t._v(" , a change in  "),a("code",[t._v("fileA.ts")]),t._v("  means that only  "),a("code",[t._v("fileA.ts")]),t._v("  and  "),a("code",[t._v("fileB.ts")]),t._v("  need to be re-checked.")]),t._v(" "),a("p",[t._v("In a codebase like Visual Studio Code, this reduced rebuild times for changes in certain files from about 14 seconds to about 1 second.\nWhile we don'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  "),a("code",[t._v("tsconfig.fullbuild.json")]),t._v("  or in CI).")]),t._v(" "),a("p",[t._v("For more details, you can "),a("a",{attrs:{href:"https://github.com/microsoft/TypeScript/pull/35711",target:"_blank",rel:"noopener noreferrer"}},[t._v("see the original pull request"),a("OutboundLink")],1),t._v(".")])])}),[],!1,null,null,null);s.default=n.exports}}]);