From 3e9c70e6c39c594389bbced884d7365b05cc98cd Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 1 Jul 2024 22:41:23 -0400 Subject: [PATCH] jsguide: import last internal version Internally, we've turned down the JS styleguide in favor of a merged TS/JS guide (with heavy emphasis on TS). That variant doesn't exist publicly yet, and even then, we probably want to keep around the JS version as-is more or less indefinitely like we have with the older ES5 guide. Once we update the TS guide, we can add a deprecation notice to this file like we do with the ES5 guide. There is one change that has been left out: the heavy emphasis on only using clang-format as the rules are heavily geared towards google3, and there is no external guidance for formatting. If we could provide public guidance here, it'd be great to update, but since the guide is no more internally, that seems unlikely, so it's probably best to freeze the pre-clang-format guidance here. --- jsguide.html | 916 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 553 insertions(+), 363 deletions(-) diff --git a/jsguide.html b/jsguide.html index d07f67e..4da5bfa 100644 --- a/jsguide.html +++ b/jsguide.html @@ -22,7 +22,7 @@ herein.

issues of formatting, but other types of conventions or coding standards as well. However, this document focuses primarily on the hard-and-fast rules that we follow universally, and avoids giving advice that isn't clearly enforceable -(whether by human or tool).

+(whether by human or tool).

1.1 Terminology notes

@@ -31,11 +31,11 @@ we follow universally, and avoids giving advice that isn't clearly enforceable
  1. The term comment always refers to implementation comments. We do not use the phrase documentation comments, instead using the common term “JSDoc” -for both human-readable text and machine-readable annotations within -/** … */.

  2. +for both human-readable text and machine-readable annotations within /** … +*/.

  3. This Style Guide uses RFC 2119 terminology when using the phrases must, -must not, should, should not, and may. The terms prefer and -avoid correspond to should and should not, respectively. Imperative +must not, should, should not, and may. The terms prefer and +avoid correspond to should and should not, respectively. Imperative and declarative statements are prescriptive and correspond to must.

@@ -65,8 +65,8 @@ uses. Filenames’ extension must be .js.

2.3.1 Whitespace characters

Aside from the line terminator sequence, the ASCII horizontal space character -(0x20) is the only whitespace character that appears anywhere in a source -file. This implies that

+(0x20) is the only whitespace character that appears anywhere in a source file. +This implies that

  1. All other whitespace characters in string literals are escaped, and

  2. @@ -109,9 +109,11 @@ are broken and they must be fixed.

    3 Source file structure

    -

    All new source files should either be a goog.module file (a file containing a -goog.module call) or an ECMAScript (ES) module (uses import and export -statements). Files consist of the following, in order:

    +

    All new source files should either be a goog.module +file (a file containing a goog.module call) or an ECMAScript (ES) module (uses +import and export statements).

    + +

    Files consist of the following, in order:

    1. License or copyright information, if present
    2. @@ -139,14 +141,14 @@ file's implementation, which may be preceded by 1 or 2 blank lines.

      line: lines containing a goog.module declaration must not be wrapped, and are therefore an exception to the 80-column limit.

      -

      The entire argument to goog.module is what defines a namespace. It is the +

      The entire argument to goog.module is what defines a namespace. It is the package name (an identifier that reflects the fragment of the directory structure where the code lives) plus, optionally, the main class/enum/interface -that it defines concatenated to the end.

      +that it defines concatenated to the end in lowerCamelCase.

      -

      Example

      +

      Example:

      -
      goog.module('search.urlHistory.UrlHistoryService');
      +
      goog.module('search.urlHistory.urlHistoryService');
       

      3.3.1 Hierarchy

      @@ -161,7 +163,7 @@ goog.module('foo.bar.baz');

      The directory hierarchy reflects the namespace hierarchy, so that deeper-nested -children are subdirectories of higher-level parent directories. Note that this +children are subdirectories of higher-level parent directories. Note that this implies that owners of “parent” namespace groups are necessarily aware of all child namespaces, since they exist in the same directory.

      @@ -186,15 +188,14 @@ namespace, this name must not be a child or parent of any other goog.module('parent.child'); cannot both exist safely, nor can goog.module('parent'); and goog.module('parent.child.grandchild');).

      -

      3.3.3 goog.module Exports

      +

      3.3.3 goog.module Exports

      Classes, enums, functions, constants, and other symbols are exported using the exports object. Exported symbols may be defined directly on the exports object, or else declared locally and exported separately. Symbols are only exported if they are meant to be used outside the module. Non-exported -module-local symbols are not declared @private nor do their names end with an -underscore. There is no prescribed ordering for exported and module-local -symbols.

      +module-local symbols are not declared @private. There is no prescribed +ordering for exported and module-local symbols.

      Examples:

      @@ -229,10 +230,18 @@ constant by the compiler.

      exports = {exportedFunction}; +

      Do not use default exports as they don't translate easily to ES module +semantics.

      + +
      exports = FancyClass;
      +
      +

      3.4 ES modules

      +

      ES modules are files that use the import and export keywords.

      +

      3.4.1 Imports

      @@ -297,6 +306,11 @@ import * as math from './math/math.js'; import * as vectorMath from './vector/math.js'; +

      Some libraries might commonly use a namespace import prefix that violates this +naming scheme, but overbearingly common open source use makes the violating +style more readable. The only library that currently falls under this exception +is threejs, using the THREE prefix.

      +
      3.4.1.3.2 Naming default imports

      Default import names are derived from the imported file name and follow the @@ -340,9 +354,8 @@ new DomesticatedCat();

      3.4.2 Exports

      Symbols are only exported if they are meant to be used outside the module. -Non-exported module-local symbols are not declared @private nor do their names -end with an underscore. There is no prescribed ordering for exported and -module-local symbols.

      +Non-exported module-local symbols are not declared @private. There is no +prescribed ordering for exported and module-local symbols.

      3.4.2.1 Named vs default exports
      @@ -366,37 +379,9 @@ class Foo { ... } export {Foo}; -
      3.4.2.2 Exporting static container classes and objects
      - -

      Do not export container classes or objects with static methods or properties for -the sake of namespacing.

      - -
      // container.js
      -// Bad: Container is an exported class that has only static methods and fields.
      -export class Container {
      -  /** @return {number} */
      -  static bar() {
      -    return 1;
      -  }
      -}
      -
      -/** @const {number} */
      -Container.FOO = 1;
      -
      - -

      Instead, export individual constants and functions:

      - -
      /** @return {number} */
      -export function bar() {
      -  return 1;
      -}
      -
      -export const /** number */ FOO = 1;
      -
      -

      -
      3.4.2.3 Mutability of exports
      +
      3.4.2.2 Mutability of exports

      Exported variables must not be mutated outside of module initialization.

      @@ -429,7 +414,7 @@ export function setMutateFoo(newMutateFoo) { // instead make them module scoped and export a getter for foo and a wrapper for // mutateFooFunc. let /** number */ foo = 0; -let /** function(number): number */ mutateFooFunc = foo => foo + 1; +let /** function(number): number */ mutateFooFunc = (foo) => foo + 1; /** @return {number} */ export function getFoo() { @@ -448,7 +433,7 @@ export function setMutateFoo(mutateFoo) {

      -
      3.4.2.4 export from
      +
      3.4.2.3 export from

      export from statements must not be line wrapped and are therefore an exception to the 80-column limit. This applies to both export from flavors.

      @@ -492,9 +477,9 @@ export let x;
      import * as goog from '../closure/goog/goog.js';
       
      -const name = goog.require('a.name');
      +const {compute} = goog.require('a.name');
       
      -export const CONSTANT = name.compute();
      +export const CONSTANT = compute();
       

      goog.js exports only a subset of properties from the global goog that can be @@ -521,7 +506,7 @@ const myNamespace = goog.require('my.namespace');

      goog.declareModuleId can be used within ES modules to declare a goog.module-like module ID. This means that this module ID can be -goog.required, goog.module.getd, goog.forwardDeclare'd, etc. as if it were +goog.required, goog.module.getd etc. as if it were a goog.module that did not call goog.module.declareLegacyNamespace. It does not create the module ID as a globally available JavaScript symbol.

      @@ -546,18 +531,19 @@ export class Class {};

      3.5 goog.setTestOnly

      -

      In a goog.module file the goog.module statement may optionally be followed -by a call to goog.setTestOnly().

      +

      In a goog.module file the goog.module statement and, if present, +goog.module.declareLegacyNamespace() statement may optionally be followed by a +call to goog.setTestOnly().

      -

      In an ES module the import statements may optionally be followed by a call to -goog.setTestOnly().

      +

      In an ES module the import statements may optionally be +followed by a call to goog.setTestOnly().

      3.6 goog.require and goog.requireType statements

      Imports are done with goog.require and goog.requireType statements. The names imported by a goog.require statement may be used both in code and in -type annotations, while those imported by a goog.requireType may be used -in type annotations only.

      +type annotations, while those imported by a goog.requireType may be used in +type annotations only.

      The goog.require and goog.requireType statements form a contiguous block with no empty lines. This block follows the goog.module declaration separated @@ -575,8 +561,8 @@ qualified namespaces must not be used anywhere, except as an argument to

      Exception: Types, variables, and functions declared in externs files have to use their fully qualified name in type annotations and code.

      -

      Aliases must match the final dot-separated component of the imported module's -namespace.

      +

      When goog.require is assigned to a single constant alias, it must match the +final dot-separated component of the imported module's namespace.

      Exception: In certain cases, additional components of the namespace can be used to form a longer alias. The resulting alias must retain the original @@ -584,8 +570,9 @@ identifier's casing such that it still correctly identifies its type. Longer aliases may be used to disambiguate otherwise identical aliases, or if it significantly improves readability. In addition, a longer alias must be used to prevent masking native types such as Element, Event, Error, Map, and -Promise (for a more complete list, see Standard Built-in Objects and Web -APIs at MDN). When renaming destructured aliases, a space must follow the colon +Promise (for a more complete list, see Standard Built-in Objects and +Web APIs at MDN).

      +When renaming destructured aliases, a space must follow the colon as required in ??.

      A file should not contain both a goog.require and a goog.requireType @@ -616,26 +603,24 @@ limit.

      Example:

      // Standard alias style.
      -const MyClass = goog.require('some.package.MyClass');
      -const MyType = goog.requireType('some.package.MyType');
      -// Namespace-based alias used to disambiguate.
      -const NsMyClass = goog.require('other.ns.MyClass');
      -// Namespace-based alias used to prevent masking native type.
      -const RendererElement = goog.require('web.renderer.Element');
      -// Out of sequence namespace-based aliases used to improve readability.
      -// Also, require lines longer than 80 columns must not be wrapped.
      -const SomeDataStructureModel = goog.requireType('identical.package.identifiers.models.SomeDataStructure');
      -const SomeDataStructureProto = goog.require('proto.identical.package.identifiers.SomeDataStructure');
      -// Standard alias style.
       const asserts = goog.require('goog.asserts');
       // Namespace-based alias used to disambiguate.
       const testingAsserts = goog.require('goog.testing.asserts');
       // Standard destructuring into aliases.
      +const {MyClass} = goog.require('some.package');
      +const {MyType} = goog.requireType('other.package');
       const {clear, clone} = goog.require('goog.array');
       const {Rgb} = goog.require('goog.color');
      -// Namespace-based destructuring into aliases in order to disambiguate.
      +// Namespace-based destructuring into aliases used to disambiguate.
      +const {MyClass: NsMyClass} = goog.require('other.ns');
       const {SomeType: FooSomeType} = goog.requireType('foo.types');
       const {clear: objectClear, clone: objectClone} = goog.require('goog.object');
      +// Namespace-based destructuring into aliases used to prevent masking native type.
      +const {Element: RendererElement} = goog.require('web.renderer');
      +// Out of sequence namespace-based aliases used to improve readability.
      +// Also, require lines longer than 80 columns must not be wrapped.
      +const {SomeDataStructure: SomeDataStructureModel} = goog.requireType('identical.package.identifiers.models');
      +const {SomeDataStructure: SomeDataStructureProto} = goog.require('proto.identical.package.identifiers');
       // goog.require without an alias in order to trigger side effects.
       /** @suppress {extraRequire} Initializes MyFramework. */
       goog.require('my.framework.initialization');
      @@ -643,6 +628,13 @@ goog.require('my.framework.initialization');
       
       

      Discouraged:

      +
      // Some legacy code uses a "default export" style to export a single class, enum,
      +// record type, etc. Do not use this pattern in new JS.
      +// When using a "default export", prefer destructuring into aliases.
      +const MyClass = goog.require('some.package.MyClass');
      +const MyType = goog.requireType('some.package.MyType');
      +
      +
      // If necessary to disambiguate, prefer PackageClass over SomeClass as it is
       // closer to the format of the module name.
       const SomeClass = goog.require('some.package.Class');
      @@ -684,20 +676,18 @@ function someFunction(param) {
       (separated by at least one blank line).

      This may consist of any module-local declarations (constants, variables, -classes, functions, etc), as well as any exported symbols. -

      +classes, functions, etc), as well as any exported symbols.

      4 Formatting

      Terminology Note: block-like construct refers to the body of a class, -function, method, or brace-delimited block of code. Note that, by +function, method, or brace-delimited block of code. Note that, by ?? and ??, any array or object literal may optionally be treated as if it were a block-like construct.

      Tip: Use clang-format. The JavaScript community has invested effort to make sure clang-format does the right thing on JavaScript files. clang-format has -integration with several popular -editors.

      +integration with several popular editors.

      4.1 Braces

      @@ -705,7 +695,7 @@ editors.

      Braces are required for all control structures (i.e. if, else, for, do, while, as well as any others), even if the body contains only a single -statement. The first statement of a non-empty block must begin on its own line.

      +statement. The first statement of a non-empty block must begin on its own line.

      Disallowed:

      @@ -717,7 +707,7 @@ for (let i = 0; i < foo.length; i++) bar(foo[i]);

      Exception: A simple if statement that can fit entirely on a single line with no wrapping (and that doesn’t have an else) may be kept on a single line with no -braces when it improves readability. This is the only case in which a control +braces when it improves readability. This is the only case in which a control structure may omit braces and newlines.

      if (shortCondition()) foo();
      @@ -734,8 +724,8 @@ structure may omit braces and newlines.

    3. Line break before the closing brace.
    4. Line break after the closing brace if that brace terminates a statement or the body of a function or class statement, or a class method. Specifically, -there is no line break after the brace if it is followed by else, catch, -while, or a comma, semicolon, or right-parenthesis.
    5. +there is no line break after the brace if it is followed by else, +catch, while, or a comma, semicolon, or right-parenthesis.

      Example:

      @@ -786,8 +776,8 @@ try {

      Each time a new block or block-like construct is opened, the indent increases by two spaces. When the block ends, the indent returns to the previous indent -level. The indent level applies to both code and comments throughout the -block. (See the example in ??).

      +level. The indent level applies to both code and comments throughout the block. +(See the example in ??).

      4.2.1 Array literals: optionally block-like

      @@ -844,38 +834,44 @@ someMethod(foo, {

      Class literals (whether declarations or expressions) are indented as blocks. Do not add semicolons after methods, or after the closing brace of a class declaration (statements—such as assignments—that contain class expressions -are still terminated with a semicolon). Use the extends keyword, but not the -@extends JSDoc annotation unless the class extends a templatized type.

      +are still terminated with a semicolon). For inheritance, the extends keyword +is sufficient unless the superclass is templatized. Subclasses of templatized +types must explicitly specify the template type in an @extends JSDoc +annotation, even if it is just passing along the same template name.

      Example:

      -
      class Foo {
      -  constructor() {
      -    /** @type {number} */
      -    this.x = 42;
      +
      /** @template T */
      +class Foo {
      +  /** @param {T} x */
      +  constructor(x) {
      +    /** @type {T} */
      +    this.x = x;
         }
      +}
       
      +/** @extends {Foo<number>} */
      +class Bar extends Foo {
      +  constructor() {
      +    super(42);
      +  }
      +}
      +
      +exports.Baz = class extends Bar {
         /** @return {number} */
         method() {
           return this.x;
         }
      -}
      -Foo.Empty = class {};
      +};
       
      -
      /** @extends {Foo<string>} */
      -foo.Bar = class extends Foo {
      -  /** @override */
      +
      /** @extends {Bar} */ // <-- unnecessary @extends
      +exports.Baz = class extends Bar {
      +  /** @return {number} */
         method() {
      -    return super.method() / 2;
      +    return this.x;
         }
       };
      -
      -/** @interface */
      -class Frobnicator {
      -  /** @param {string} message */
      -  frobnicate(message) {}
      -}
       

      4.2.4 Function expressions

      @@ -1020,6 +1016,11 @@ operator.
    6. A method or constructor name stays attached to the open parenthesis (() that follows it.
    7. A comma (,) stays attached to the token that precedes it.
    8. +
    9. A line break is never added between a return and the return value as this +would change the meaning of the code.
    10. +
    11. JSDoc annotations with type names break after {. This is necessary as +annotations with optional types (@const, @private, @param, etc) do not scan +the next line.
    @@ -1034,7 +1035,7 @@ indented at least +4 from the original line, unless it falls under the rules of block indentation.

    When there are multiple continuation lines, indentation may be varied beyond +4 -as appropriate. In general, continuation lines at a deeper syntactic level are +as appropriate. In general, continuation lines at a deeper syntactic level are indented by larger multiples of 4, and two lines use the same indentation level if and only if they begin with syntactically parallel elements.

    @@ -1050,8 +1051,8 @@ using a variable number of spaces to align certain tokens with previous lines.
  3. Between consecutive methods in a class or object literal
      -
    1. Exception: A blank line between two consecutive properties definitions in -an object literal (with no other code between them) is optional. Such +
    2. Exception: A blank line between two consecutive properties definitions +in an object literal (with no other code between them) is optional. Such blank lines are used as needed to create logical groupings of fields.
  4. Within method bodies, sparingly to create logical groupings of statements. @@ -1069,8 +1070,8 @@ encouraged).

    Use of horizontal whitespace depends on location, and falls into three broad categories: leading (at the start of a line), trailing (at the end of a -line), and internal. Leading whitespace (i.e., indentation) is addressed -elsewhere. Trailing whitespace is forbidden.

    +line), and internal. Leading whitespace (i.e., indentation) is addressed +elsewhere. Trailing whitespace is forbidden.

    Beyond where required by the language or other style rules, and apart from literals, comments, and JSDoc, a single internal ASCII space also appears in the @@ -1107,11 +1108,11 @@ Here, multiple spaces are allowed, but not required.

  5. variable number of additional spaces in your code with the goal of making certain tokens appear directly below certain other tokens on previous lines.

    -

    This practice is permitted, but it is generally discouraged by Google -Style. It is not even required to maintain horizontal alignment in places -where it was already used.

    +

    This practice is permitted, but it is generally discouraged by Google Style. +It is not even required to maintain horizontal alignment in places where it +was already used.

    -

    Here is an example without alignment, followed by one with alignment. Both are +

    Here is an example without alignment, followed by one with alignment. Both are allowed, but the latter is discouraged:

    {
    @@ -1127,16 +1128,21 @@ allowed, but the latter is discouraged:

    Tip: Alignment can aid readability, but it creates problems for future maintenance. Consider a future change that needs to touch just one line. This -change may leave the formerly-pleasing formatting mangled, and that is -allowed. More often it prompts the coder (perhaps you) to adjust whitespace on -nearby lines as well, possibly triggering a cascading series of -reformattings. That one-line change now has a blast radius. This can at worst -result in pointless busywork, but at best it still corrupts version history -information, slows down reviewers and exacerbates merge conflicts.

    +change may leave the formerly-pleasing formatting mangled, and that is allowed. +More often it prompts the coder (perhaps you) to adjust whitespace on nearby +lines as well, possibly triggering a cascading series of reformattings. That +one-line change now has a blast radius. This can at worst result in pointless +busywork, but at best it still corrupts version history information, slows down +reviewers and exacerbates merge conflicts.

    4.6.4 Function arguments

    -

    Prefer to put all function arguments on the same line as the function name. If doing so would exceed the 80-column limit, the arguments must be line-wrapped in a readable way. To save space, you may wrap as close to 80 as possible, or put each argument on its own line to enhance readability. Indentation should be four spaces. Aligning to the parenthesis is allowed, but discouraged. Below are the most common patterns for argument wrapping:

    +

    Prefer to put all function arguments on the same line as the function name. If +doing so would exceed the 80-column limit, the arguments must be line-wrapped in +a readable way. To save space, you may wrap as close to 80 as possible, or put +each argument on its own line to enhance readability. Indentation should be four +spaces. Aligning to the parenthesis is allowed, but discouraged. Below are the +most common patterns for argument wrapping:

    // Arguments start on a new line, indented four spaces. Preferred when the
     // arguments don't fit on the same line with the function name (or the keyword
    @@ -1223,17 +1229,20 @@ Their preferred format is before the value with =:

    5 Language features

    -

    JavaScript includes many dubious (and even dangerous) features. This section +

    JavaScript includes many dubious (and even dangerous) features. This section delineates which features may or may not be used, and any additional constraints on their use.

    +

    Language features which are not discussed in this style guide may be used with +no recommendations of their usage.

    +

    5.1 Local variable declarations

    5.1.1 Use const and let

    -

    Declare all local variables with either const or let. Use const by default, -unless a variable needs to be reassigned. The var -keyword must not be used.

    +

    Declare all local variables with either const or let. Use const by +default, unless a variable needs to be reassigned. The var keyword +must not be used.

    5.1.2 One variable per declaration

    @@ -1244,7 +1253,8 @@ as let a = 1, b = 2; are not used.

    Local variables are not habitually declared at the start of their containing block or block-like construct. Instead, local variables are declared close to -the point they are first used (within reason), to minimize their scope.

    +the point they are first used (within reason), to minimize their scope, and +initialized as soon as possible.

    5.1.4 Declare types as needed

    @@ -1270,10 +1280,10 @@ const /** !Array<number> */ data = [];

    Tip: There are many cases where the compiler can infer a templatized type but -not its parameters. This is particularly the case when the initializing literal +not its parameters. This is particularly the case when the initializing literal or constructor call does not include any values of the template parameter type (e.g., empty arrays, objects, Maps, or Sets), or if the variable is modified -in a closure. Local variable type annotations are particularly helpful in these +in a closure. Local variable type annotations are particularly helpful in these cases since otherwise the compiler will infer the template parameter as unknown.

    5.2 Array literals

    @@ -1324,14 +1334,14 @@ allowed when appropriate.

    5.2.3 Non-numeric properties

    -

    Do not define or use non-numeric properties on an array (other than -length). Use a Map (or Object) instead.

    +

    Do not define or use non-numeric properties on an array (other than length). +Use a Map (or Object) instead.

    5.2.4 Destructuring

    Array literals may be used on the left-hand side of an assignment to perform destructuring (such as when unpacking multiple values from a single array or -iterable). A final rest element may be included (with no space between the +iterable). A final rest element may be included (with no space between the ... and the variable name). Elements should be omitted if they are unused.

    const [a, b, c, ...rest] = generateResults();
    @@ -1359,8 +1369,8 @@ naming the individual elements and specifying a different type for each.

    5.2.5 Spread operator

    Array literals may include the spread operator (...) to flatten elements out -of one or more other iterables. The spread operator should be used instead of -more awkward constructs with Array.prototype. There is no space after the +of one or more other iterables. The spread operator should be used instead of +more awkward constructs with Array.prototype. There is no space after the ....

    Example:

    @@ -1484,11 +1494,12 @@ to perform destructuring and unpack multiple values from a single object.

    Destructured objects may also be used as function parameters, but should be kept as simple as possible: a single level of unquoted shorthand properties. Deeper levels of nesting and computed properties may not be used in parameter -destructuring. Specify any default values in the left-hand-side of the -destructured parameter ({str = 'some default'} = {}, rather than {str} = {str: 'some default'}), and if a destructured -object is itself optional, it must default to {}. The JSDoc for the -destructured parameter may be given any name (the name is unused but is required -by the compiler).

    +destructuring. Specify any default values in the left-hand-side of the +destructured parameter ({str = 'some default'} = {}, rather than +{str} = {str: 'some default'}), and if a +destructured object is itself optional, it must default to {}. The JSDoc for +the destructured parameter may be given any name (the name is unused but is +required by the compiler).

    Example:

    @@ -1498,7 +1509,7 @@ by the compiler).

    * num: The number of times to do something. * str: A string to do stuff to. */ -function destructured(ordinary, {num, str = 'some default'} = {}) +function destructured(ordinary, {num, str = 'some default'} = {}) {}

    Disallowed:

    @@ -1520,8 +1531,11 @@ long it is (see ??).

    5.3.8 Enums

    Enumerations are defined by adding the @enum annotation to an object literal. -Additional properties may not be added to an enum after it is defined. Enums -must be constant, and all enum values must be deeply immutable.

    +Enums must be module-local or assigned directly on exports, not nested under a +type or object.

    + +

    Additional properties may not be added to an enum after it is defined. Enums +must be constant. All enum values must be either a string literal or a number.

    /**
      * Supported temperature scales.
    @@ -1533,17 +1547,41 @@ const TemperatureScale = {
     };
     
     /**
    - * An enum with two options.
    + * An enum with two values.
      * @enum {number}
      */
    -const Option = {
    -  /** The option used shall have been the first. */
    -  FIRST_OPTION: 1,
    -  /** The second among two options. */
    -  SECOND_OPTION: 2,
    +const Value = {
    +  /** The value used shall have been the first. */
    +  FIRST_VALUE: 1,
    +  /** The second among two values. */
    +  SECOND_VALUE: 2,
     };
     
    +

    For string enums, all values must be statically initialized and not computed +using arithmetic operators, template literal substitution, function calls or +even a variable reference.

    + +
    const ABSOLUTE_ZERO = '-273°F';
    +
    +/**
    + * Not supported computed values in string enum.
    + * @enum {string}
    + */
    +const TemperatureInFahrenheit = {
    +  MIN_POSSIBLE: ABSOLUTE_ZERO,
    +  ZERO_FAHRENHEIT: 0 + '°F',
    +  ONE_FAHRENHEIT: `${Values.FIRST_VALUE}°F`,
    +  TWO_FAHRENHEIT: Values.SECOND_VALUE + '°F',
    +  SOME_FAHRENHEIT: getTemperatureInFahrenheit() + '°F',
    +};
    +
    + +

    Note: Although TypeScript supports a few more patterns for enum values (e.g A: +'a'+'b', etc), the restriction of only allowing string literals and numbers for +enum values is to aid migration to TypeScript. For complex values consider using +a const object without @enum.

    +

    5.4 Classes

    5.4.1 Constructors

    @@ -1554,12 +1592,13 @@ non-method properties in the constructor.

    5.4.2 Fields

    -

    Set all of a concrete object’s fields (i.e. all properties other than methods) -in the constructor. Annotate fields that are never reassigned with @const -(these need not be deeply immutable). Annotate non-public fields with the proper -visibility annotation (@private, @protected, @package), and end all -@private fields' names with an underscore. Fields are never set on a concrete -class' prototype.

    +

    Define all of a concrete object’s fields (i.e. all properties other than +methods) in the constructor. Annotate fields that are never reassigned with +@const (these need not be deeply immutable). Annotate non-public fields with +the proper visibility annotation (@private, @protected, @package). +@private fields' names may optionally end with an underscore. Fields must not +be defined within a nested scope in the constructor nor on a concrete class's +prototype.

    Example:

    @@ -1576,22 +1615,24 @@ class' prototype.

    Tip: Properties should never be added to or removed from an instance after the constructor is finished, since it significantly hinders VMs’ ability to -optimize. If necessary, fields that are initialized later should be explicitly +optimize. If necessary, fields that are initialized later should be explicitly set to undefined in the constructor to prevent later shape changes. Adding @struct to an object will check that undeclared properties are not -added/accessed. Classes have this added by default.

    +added/accessed. Classes have this added by default.

    5.4.3 Computed properties

    -

    Computed properties may only be used in classes when the property is a -symbol. Dict-style properties (that is, quoted or computed non-symbol keys, as -defined in ??) are not allowed. A -[Symbol.iterator] method should be defined for any classes that are logically -iterable. Beyond this, Symbol should be used sparingly.

    +

    Computed properties may only be used in classes when the property is a symbol. +Dict-style properties (that is, quoted or computed non-symbol keys, as defined +in ??) are not allowed. A [Symbol.iterator] +method should be defined for any classes that are logically iterable. Beyond +this, Symbol should be used sparingly.

    -

    Tip: be careful of using any other built-in symbols (e.g., Symbol.isConcatSpreadable) as they are not polyfilled by the compiler and will therefore not work in older browsers.

    +

    Tip: be careful of using any other built-in symbols (e.g., +Symbol.isConcatSpreadable) as they are not polyfilled by the compiler and will +therefore not work in older browsers.

    5.4.4 Static methods

    @@ -1600,24 +1641,41 @@ iterable. Beyond this, Symbol should be used sparingly.

    Where it does not interfere with readability, prefer module-local functions over private static methods.

    -

    Static methods should only be called on the base class itself. Static methods -should not be called on variables containing a dynamic instance that may be -either the constructor or a subclass constructor (and must be defined with -@nocollapse if this is done), and must not be called directly on a subclass -that doesn’t define the method itself.

    +

    Code should not rely on dynamic dispatch of static methods, because it +interferes with Closure Compiler optimizations. Static methods should only be +called on the base class itself. Static methods should not be called on +variables containing a dynamic instance that may be either the constructor or a +subclass constructor (and must be defined with @nocollapse if this is done), +and must not be called directly on a subclass that doesn’t define the method +itself. Do not access this in static methods.

    Disallowed:

    -
    class Base { /** @nocollapse */ static foo() {} }
    +
    // Context for the examples below; by itself this code is allowed.
    +class Base {
    +  /** @nocollapse */ static foo() {}
    +}
     class Sub extends Base {}
    -function callFoo(cls) { cls.foo(); }  // discouraged: don't call static methods dynamically
    -Sub.foo();  // Disallowed: don't call static methods on subclasses that don't define it themselves
    +
    +// discouraged: don't call static methods dynamically
    +function callFoo(cls) { cls.foo(); }
    +
    +// Disallowed: don't call static methods on subclasses that don't define it themselves
    +Sub.foo();
    +
    +// Disallowed: don't access this in static methods.
    +class Clazz {
    +  static foo() {
    +    return this.staticField;
    +  }
    +}
    +Class.staticField = 1;
     

    5.4.5 Old-style class declarations

    While ES6 classes are preferred, there are cases where ES6 classes may not be -feasible. For example:

    +feasible. For example:

    1. If there exist or will exist subclasses, including frameworks that create @@ -1625,8 +1683,8 @@ subclasses, that cannot be immediately changed to use ES6 class syntax. If such a class were to use ES6 syntax, all downstream subclasses not using ES6 class syntax would need to be modified.

    2. Frameworks that require a known this value before calling the superclass -constructor, since constructors with ES6 super classes do not have -access to the instance this value until the call to super returns.

    3. +constructor, since constructors with ES6 super classes do not have access to +the instance this value until the call to super returns.

    In all other ways the style guide still applies to this code: let, const, @@ -1679,9 +1737,13 @@ C.prototype.method = function(param) { };

    -

    Per-instance properties should be defined in the constructor after the call to the super class constructor, if there is a super class. Methods should be defined on the prototype of the constructor.

    +

    Per-instance properties should be defined in the constructor after the call to +the super class constructor, if there is a super class. Methods should be +defined on the prototype of the constructor.

    -

    Defining constructor prototype hierarchies correctly is harder than it first appears! For that reason, it is best to use goog.inherits from the Closure Library .

    +

    Defining constructor prototype hierarchies correctly is harder than it first +appears! For that reason, it is best to use goog.inherits from +the Closure Library .

    5.4.6 Do not manipulate prototypes directly

    @@ -1691,21 +1753,21 @@ manipulating these objects, though they are still useful for defining classes as defined in ??. Mixins and modifying the prototypes of builtin objects are explicitly forbidden.

    -

    Exception: Framework code (such as Polymer, or Angular) may need to use prototypes, and should not -resort to even-worse workarounds to avoid doing so.

    +

    Exception: Framework code (such as Polymer, or Angular) may need to use prototypes, and should not resort +to even-worse workarounds to avoid doing so.

    5.4.7 Getters and Setters

    -

    Do not use JavaScript getter and setter properties. They are potentially +

    Do not use JavaScript getter and setter properties. They are potentially surprising and difficult to reason about, and have limited support in the -compiler. Provide ordinary methods instead.

    +compiler. Provide ordinary methods instead.

    Exception: there are situations where defining a getter or setter is unavoidable (e.g. data binding frameworks such as Angular and Polymer, or for -compatibility with external APIs that cannot be adjusted). In these cases only, +compatibility with external APIs that cannot be adjusted). In these cases only, getters and setters may be used with caution, provided they are defined with the get and set shorthand method keywords or Object.defineProperties (not -Object.defineProperty, which interferes with property renaming). Getters +Object.defineProperty, which interferes with property renaming). Getters must not change observable state.

    Disallowed:

    @@ -1729,8 +1791,9 @@ exceptional conditions could lead to infinite loops.

    with @record can be explicitly (i.e. via @implements) or implicitly implemented by a class or object literal.

    -

    All non-static method bodies on an interface must be empty blocks. Fields must -be declared as uninitialized members in the class constructor.

    +

    All methods on an interface must be non-static and method bodies must be empty +blocks. Fields must be declared as uninitialized members in the class +constructor.

    Example:

    @@ -1756,8 +1819,96 @@ class Frobnicator {

    5.4.10 Abstract Classes

    Use abstract classes when appropriate. Abstract classes and methods must be -annotated with @abstract. Do not use goog.abstractMethod. See abstract -classes and methods.

    +annotated with @abstract. Do not use goog.abstractMethod. See +abstract classes and methods.

    + +

    5.4.11 Do not create static container classes

    + +

    Do not use container classes with only static methods or properties for the sake +of namespacing.

    + +
    // container.js
    +// Bad: Container is an exported class that has only static methods and fields.
    +class Container {
    +  /** @return {number} */
    +  static bar() {
    +    return 1;
    +  }
    +}
    +
    +/** @const {number} */
    +Container.FOO = 1;
    +
    +exports = {Container};
    +
    + +

    Instead, export individual constants and functions:

    + +
    /** @return {number} */
    +exports.bar = () => {
    +  return 1;
    +}
    +
    +/** @const {number} */
    +exports.FOO = 1;
    +
    + +

    5.4.12 Do not define nested namespaces

    + +

    Do not define a nested type (e.g. class, typedef, enum, interface) on another +module-local name.

    + +
    // foo.js
    +goog.module('my.namespace');
    +
    +class Foo {...}
    +
    +Foo.Bar = class {...};
    +
    +/** @enum {number} */
    +Foo.Baz = {...};
    +
    +/** @typedef {{value: number}} */
    +Foo.Qux;
    +
    +/** @interface */
    +Foo.Quuz = class {...}
    +
    +exports.Foo = Foo;
    +
    + +

    These values should be top-level exports. Choose clear names for these values +(e.g. FooConverter for a Converter that could have been nested on Foo). However, +when the module name is redundant with part of the class name, consider omitting +the redundancy: foo.Foo and foo.Converter rather than foo.Foo and +foo.FooConverter. Importers can add the prefix when necessary for clarity +(e.g. import {Converter as FooConverter} from './foo';) but cannot easily +remove the redundancy when importing the entire module as a namespace.

    + +
    // foo.js
    +goog.module('my.namespace');
    +
    +class Foo {...}
    +
    +class FooBar {...}
    +
    +/** @enum {string} */
    +let FooBaz = {...};
    +
    +/** @typedef {{value: number}} */
    +let FooQux;
    +
    +/** @interface */
    +class FooQuuz {...};
    +
    +export = {
    +  Foo,
    +  FooBar,
    +  FooBaz,
    +  FooQux,
    +  FooQuuz,
    +};
    +

    5.5 Functions

    @@ -1785,15 +1936,14 @@ exports = {processString};

    5.5.2 Nested functions and closures

    -

    Functions may contain nested function definitions. If it is useful to give the +

    Functions may contain nested function definitions. If it is useful to give the function a name, it should be assigned to a local const.

    5.5.3 Arrow functions

    Arrow functions provide a concise function syntax and simplify scoping this -for nested functions. Prefer arrow functions over the function keyword, -particularly for nested functions (but see -??).

    +for nested functions. Prefer arrow functions over the function keyword for +nested functions (but see ??).

    Prefer arrow functions over other this scoping approaches such as f.bind(this), goog.bind(f, this), and const self = this. Arrow functions @@ -1863,7 +2013,7 @@ const moduleLocalFunc = () => anotherFunction();

    Generators enable a number of useful abstractions and may be used as needed.

    When defining generator functions, attach the * to the function keyword when -present, and separate it with a space from the name of the function. When using +present, and separate it with a space from the name of the function. When using delegating yields, attach the * to the yield keyword.

    Example:

    @@ -1922,8 +2072,8 @@ class MyInterface {

    Use default parameters sparingly. Prefer destructuring (as in -??) to create readable APIs when there -are more than a small handful of optional parameters that do not have a natural +??) to create readable APIs when there are +more than a small handful of optional parameters that do not have a natural order.

    Note: Unlike Python's default parameters, it is okay to use initializers that @@ -1941,7 +2091,7 @@ coupling between function calls.

    Use a rest parameter instead of accessing arguments. Rest parameters are typed with a ... prefix in their JSDoc. The rest parameter must be the last parameter in the list. There is no space between the ... and the parameter -name. Do not name the rest parameter var_args. Never name a local variable or +name. Do not name the rest parameter var_args. Never name a local variable or parameter arguments, which confusingly shadows the built-in name.

    Example:

    @@ -1960,9 +2110,9 @@ the JSDoc above the function or method definition.

    5.5.7 Spread operator

    -

    Function calls may use the spread operator (...). Prefer the spread operator +

    Function calls may use the spread operator (...). Prefer the spread operator to Function.prototype.apply when an array or iterable is unpacked into -multiple parameters of a variadic function. There is no space after the ....

    +multiple parameters of a variadic function. There is no space after the ....

    Example:

    @@ -2026,37 +2176,37 @@ after the slash, and is less obvious to readers.

    5.7 Number literals

    -

    Numbers may be specified in decimal, hex, octal, or binary. Use exactly 0x, +

    Numbers may be specified in decimal, hex, octal, or binary. Use exactly 0x, 0o, and 0b prefixes, with lowercase letters, for hex, octal, and binary, -respectively. Never include a leading zero unless it is immediately followed by +respectively. Never include a leading zero unless it is immediately followed by x, o, or b.

    5.8 Control structures

    5.8.1 For loops

    -

    With ES6, the language now has three different kinds of for loops. All may be +

    With ES6, the language now has three different kinds of for loops. All may be used, though for-of loops should be preferred when possible.

    for-in loops may only be used on dict-style objects (see ??), and should not be used to iterate over an -array. Object.prototype.hasOwnProperty should be used in for-in loops to -exclude unwanted prototype properties. Prefer for-of and Object.keys over +array. Object.prototype.hasOwnProperty should be used in for-in loops to +exclude unwanted prototype properties. Prefer for-of and Object.keys over for-in when possible.

    5.8.2 Exceptions

    Exceptions are an important part of the language and should be used whenever -exceptional cases occur. Always throw Errors or subclasses of Error: never -throw string literals or other objects. Always use new when constructing an +exceptional cases occur. Always throw Errors or subclasses of Error: never +throw string literals or other objects. Always use new when constructing an Error.

    This treatment extends to Promise rejection values as Promise.reject(obj) is equivalent to throw obj; in async functions.

    Custom exceptions provide a great way to convey additional error information -from functions. They should be defined and used wherever the native Error -type is insufficient.

    +from functions. They should be defined and used wherever the native Error type +is insufficient.

    Prefer throwing exceptions over ad-hoc error-handling approaches (such as passing an error container reference type, or returning an object with an error @@ -2090,16 +2240,18 @@ since this will catch the error thrown by fail. Use assertThr

    5.8.3 Switch statements

    -

    Terminology Note: Inside the braces of a switch block are one or more statement groups. Each statement group consists of one or more switch labels (either case FOO: or default:), followed by one or more statements.

    +

    Terminology Note: Inside the braces of a switch block are one or more statement +groups. Each statement group consists of one or more switch labels (either case +FOO: or default:), followed by one or more statements.

    5.8.3.1 Fall-through: commented

    Within a switch block, each statement group either terminates abruptly (with a break, return or thrown exception), or is marked with a comment to -indicate that execution will or might continue into the next statement -group. Any comment that communicates the idea of fall-through is sufficient -(typically // fall through). This special comment is not required in the last -statement group of the switch block.

    +indicate that execution will or might continue into the next statement group. +Any comment that communicates the idea of fall-through is sufficient (typically +// fall through). This special comment is not required in the last statement +group of the switch block.

    Example:

    @@ -2149,14 +2301,14 @@ target of an event, or unnecessarily call()ed or apply()5.11.1 with -

    Do not use the with keyword. It makes your code harder to understand and has +

    Do not use the with keyword. It makes your code harder to understand and has been banned in strict mode since ES5.

    5.11.2 Dynamic code evaluation

    Do not use eval or the Function(...string) constructor (except for code -loaders). These features are potentially dangerous and simply do not work in -CSP environments.

    +loaders). These features are potentially dangerous and simply do not work in CSP +environments.

    5.11.3 Automatic semicolon insertion

    @@ -2165,13 +2317,13 @@ declarations, as noted above).

    5.11.4 Non-standard features

    -

    Do not use non-standard features. This includes old features that have been +

    Do not use non-standard features. This includes old features that have been removed (e.g., WeakMap.clear), new features that are not yet standardized (e.g., the current TC39 working draft, proposals at any stage, or proposed but not-yet-complete web standards), or proprietary features that are only -implemented in some browsers. Use only features defined in the current ECMA-262 -or WHATWG standards. (Note that projects writing against specific APIs, such as -Chrome extensions or Node.js, can obviously use those APIs). Non-standard +implemented in some browsers. Use only features defined in the current ECMA-262 +or WHATWG standards. (Note that projects writing against specific APIs, such as +Chrome extensions or Node.js, can obviously use those APIs). Non-standard language “extensions” (such as those provided by some external transpilers) are forbidden.

    @@ -2198,12 +2350,12 @@ if (!x) alert(typeof x); // alerts 'boolean', as expected

    5.11.6 Modifying builtin objects

    Never modify builtin types, either by adding methods to their constructors or to -their prototypes. Avoid depending on libraries that do this. Note that the +their prototypes. Avoid depending on libraries that do this. Note that the JSCompiler’s runtime library will provide standards-compliant polyfills where possible; nothing else may modify builtin objects.

    -

    Do not add symbols to the global object unless absolutely necessary -(e.g. required by a third-party API).

    +

    Do not add symbols to the global object unless absolutely necessary (e.g. +required by a third-party API).

    5.11.7 Omitting () when invoking a constructor

    @@ -2257,30 +2409,37 @@ cstmrId // Deletes internal letters. kSecondsPerDay // Do not use Hungarian notation.
    +

    Exception: Variables that are in scope for 10 lines or fewer, including +arguments that are not part of an exported API, may use short (e.g. single +letter) variable names.

    +

    6.2 Rules by identifier type

    6.2.1 Package names

    -

    Package names are all lowerCamelCase. For example, -my.exampleCode.deepSpace, but not my.examplecode.deepspace or my.example_code.deep_space.

    +

    Package names are all lowerCamelCase. For example, my.exampleCode.deepSpace, +but not my.examplecode.deepspace or +my.example_code.deep_space.

    + +

    Exception: The package name may conform to TypeScript's path-based pattern. This is +typically all lower case with underscores where present in filenames.

    6.2.2 Class names

    Class, interface, record, and typedef names are written in UpperCamelCase. -Unexported classes are simply locals: they are not marked @private and -therefore are not named with a trailing underscore.

    +Unexported classes are simply locals: they are not marked @private.

    Type names are typically nouns or noun phrases. For example, Request, -ImmutableList, or VisibilityMode. Additionally, interface names may +ImmutableView, or VisibilityMode. Additionally, interface names may sometimes be adjectives or adjective phrases instead (for example, Readable).

    6.2.3 Method names

    -

    Method names are written in lowerCamelCase. Names for @private methods must -end with a trailing underscore.

    +

    Method names are written in lowerCamelCase. Names for @private methods may +optionally end with a trailing underscore.

    Method names are typically verbs or verb phrases. For example, sendMessage or -stop_. Getter and setter methods for properties are never required, but if +stop_. Getter and setter methods for properties are never required, but if they are used they should be named getFoo (or optionally isFoo or hasFoo for booleans), or setFoo(value) for setters.

    @@ -2292,7 +2451,7 @@ components of the name. One typical pattern is

    6.2.4 Enum names

    Enum names are written in UpperCamelCase, similar to classes, and should -generally be singular nouns. Individual items within the enum are named in +generally be singular nouns. Individual items within the enum are named in CONSTANT_CASE.

    6.2.5 Constant names

    @@ -2315,16 +2474,25 @@ intending to never mutate the object is generally not enough.

    // Constants
     const NUMBER = 5;
    -/** @const */ exports.NAMES = ImmutableList.of('Ed', 'Ann');
    +/** @const */ exports.NAMES = goog.debug.freeze(['Ed', 'Ann']);
     /** @enum */ exports.SomeEnum = { ENUM_CONSTANT: 'value' };
     
     // Not constants
     let letVariable = 'non-const';
    -class MyClass { constructor() { /** @const {string} */ this.nonStatic = 'non-static'; } };
    -/** @type {string} */ MyClass.staticButMutable = 'not @const, can be reassigned';
    +
    +class MyClass {
    +  constructor() { /** @const {string} */ this.nonStatic = 'non-static'; }
    +};
    +/** @type {string} */
    +MyClass.staticButMutable = 'not @const, can be reassigned';
    +
     const /** Set<string> */ mutableCollection = new Set();
    -const /** ImmutableSet<SomeMutableType> */ mutableElements = ImmutableSet.of(mutable);
    -const Foo = goog.require('my.Foo');  // mirrors imported name
    +
    +const /** MyImmutableContainer<SomeMutableType> */ stillMutable =
    +    new MyImmutableContainer(mutableInner);
    +
    +const {Foo} = goog.require('my.foo');  // mirrors imported name
    +
     const logger = log.getLogger('loggers.are.not.immutable');
     
    @@ -2333,9 +2501,9 @@ const logger = log.getLogger('loggers.are.not.immutable');
    6.2.5.2 Local aliases

    Local aliases should be used whenever they improve readability over -fully-qualified names. Follow the same rules as goog.requires +fully-qualified names. Follow the same rules as goog.requires (??), maintaining the last part of the aliased name. -Aliases may also be used within functions. Aliases must be const.

    +Aliases may also be used within functions. Aliases must be const.

    Examples:

    @@ -2347,21 +2515,21 @@ const {assert, assertInstanceof} = asserts;

    6.2.6 Non-constant field names

    Non-constant field names (static or otherwise) are written in lowerCamelCase, -with a trailing underscore for private fields.

    +with an optional trailing underscore for private fields.

    These names are typically nouns or noun phrases. For example, computedValues or index_.

    6.2.7 Parameter names

    -

    Parameter names are written in lowerCamelCase. Note that this applies even if +

    Parameter names are written in lowerCamelCase. Note that this applies even if the parameter expects a constructor.

    One-character parameter names should not be used in public methods.

    Exception: When required by a third-party framework, parameter names may -begin with a $. This exception does not apply to any other identifiers -(e.g. local variables or properties).

    +begin with a $. This exception does not apply to any other identifiers (e.g. +local variables or properties).

    6.2.8 Local variable names

    @@ -2378,8 +2546,8 @@ identifiers, and must be all-caps, such as TYPE or THIS6.2.10 Module-local names

    Module-local names that are not exported are implicitly private. They are not -marked @private and do not end in an underscore. This applies to classes, -functions, variables, constants, enums, and other module-local identifiers.

    +marked @private. This applies to classes, functions, variables, constants, +enums, and other module-local identifiers.

    6.3 Camel case: defined

    @@ -2405,15 +2573,15 @@ recommendation does not apply.
  6. Now lowercase everything (including acronyms), then uppercase only the first character of:
      -
    1. … each word, to yield upper camel case, or
    2. -
    3. … each word except the first, to yield lower camel case
    4. +
    5. … each word, to yield UpperCamelCase, or
    6. +
    7. … each word except the first, to yield lowerCamelCase
  7. Finally, join all the words into a single identifier.

Note that the casing of the original words is almost entirely disregarded.

-

Examples:

+

Examples of lowerCamelCase:

@@ -2427,39 +2595,44 @@ character of: - - + + - - + + - - + + - - + + - - + +
XML HTTP requestXmlHttpRequestXMLHTTPRequestxmlHttpRequestXMLHTTPRequest
new customer IDnewCustomerIdnewCustomerIDnewCustomerIdnewCustomerID
inner stopwatchinnerStopwatchinnerStopWatchinnerStopwatchinnerStopWatch
supports IPv6 on iOS?supportsIpv6OnIossupportsIPv6OnIOSsupportsIpv6OnIossupportsIPv6OnIOS
YouTube importerYouTubeImporterYoutubeImporter*youTubeImporteryoutubeImporter*

*Acceptable, but not recommended.

-

Note: Some words are ambiguously hyphenated in the English language: for example nonempty and non-empty are both correct, so the method names checkNonempty and checkNonEmpty are likewise both correct.

+

For examples of UpperCamelCase, uppercase the first letter of each correct +lowerCamelCase example.

+ +

Note: Some words are ambiguously hyphenated in the English language: for example +nonempty and non-empty are both correct, so the method names checkNonempty +and checkNonEmpty are likewise both correct.

7 JSDoc

-

JSDoc is used on all classes, fields, and methods.

+

JSDoc is used on all classes, fields, and methods.

7.1 General form

@@ -2483,7 +2656,7 @@ this.foo_ = foo; multi-line style with /** and */ on their own lines.

Many tools extract metadata from JSDoc comments to perform code validation and -optimization. As such, these comments must be well-formed.

+optimization. As such, these comments must be well-formed.

7.2 Markdown

@@ -2518,8 +2691,8 @@ ignore plain text formatting, so if you did this:

7.3 JSDoc tags

-

Google style allows a subset of JSDoc tags. See -?? for the complete list. Most tags must +

Google style allows a subset of JSDoc tags. See +?? for the complete list. Most tags must occupy their own line, with the tag at the beginning of the line.

Disallowed:

@@ -2537,7 +2710,7 @@ optional type when appropriate.

/**
  * Place more complex annotations (like "implements" and "template")
- * on their own lines.  Multiple simple tags (like "export" and "final")
+ * on their own lines. Multiple simple tags (like "export" and "final")
  * may be combined in one line.
  * @export @final
  * @implements {Iterable<TYPE>}
@@ -2559,12 +2732,12 @@ class MyClass {
 consistent.

For general information about annotating types in JavaScript see -Annotating JavaScript for the Closure Compiler and Types in the Closure Type -System.

+Annotating JavaScript for the Closure Compiler and +Types in the Closure Type System.

7.4 Line wrapping

-

Line-wrapped block tags are indented four spaces. Wrapped description text may +

Line-wrapped block tags are indented four spaces. Wrapped description text may be lined up with the description on previous lines, but this horizontal alignment is discouraged.

@@ -2584,8 +2757,9 @@ exports.method = function(foo) {

7.5 Top/file-level comments

-

A file may have a top-level file overview. A copyright notice , author information, and -default visibility level are optional. File overviews are generally recommended whenever a +

A file may have a top-level file overview. A copyright notice, author information, +and default visibility level are optional. +File overviews are generally recommended whenever a file consists of more than a single class definition. The top level comment is designed to orient readers unfamiliar with the code to what is in this file. If present, it may provide a description of the file's contents and any @@ -2607,9 +2781,10 @@ template parameters, implemented interfaces, visibility, or other appropriate tags. The class description should provide the reader with enough information to know how and when to use the class, as well as any additional considerations necessary to correctly use the class. Textual descriptions may be omitted on the -constructor. @constructor and @extends annotations are not used with the -class keyword unless the class is being used to declare an @interface or -it extends a generic class.

+constructor. When defining a class @constructor and @extends annotations are +not used with the class keyword unless it extends a generic class. When +defining an @interface or a @record, the @extends annotation is used when +defining a subclass and the extends keyword is never used.

/**
  * A fancier event target that does cool things.
@@ -2664,18 +2839,17 @@ const BandersnatchType = {
 

Typedefs are useful for defining short record types, or aliases for unions, -complex functions, or generic types. -Typedefs should be avoided for record types with many fields, since they do not -allow documenting individual fields, nor using templates or recursive -references. -For large record types, prefer @record.

+complex functions, or generic types. Typedefs should be avoided for record types +with many fields, since they do not allow documenting individual fields, nor +using templates or recursive references. For large record types, prefer +@record.

7.8 Method and function comments

In methods and named functions, parameter and return types must be documented, -except in the case of same-signature @overrides, where all types are omitted. -The this type should be documented when necessary. Return type may be omitted -if the function has no non-empty return statements.

+even in the case of same-signature @overrides. The this type should be +documented when necessary. Return type may be omitted if the function has no +non-empty return statements.

Method, parameter, and return descriptions (but not types) may be omitted if they are obvious from the rest of the method’s JSDoc or from its signature.

@@ -2685,10 +2859,9 @@ does. This phrase is not an imperative sentence, but instead is written in the third person, as if there is an implied This method ... before it.

If a method overrides a superclass method, it must include an @override -annotation. Overridden methods inherit all JSDoc annotations from the super -class method (including visibility annotations) and they should be omitted in -the overridden method. However, if any type is refined in type annotations, all -@param and @return annotations must be specified explicitly.

+annotation. For overridden methods, all @param and @return annotations must +be specified explicitly even if no type from the superclass method is refined. +This is to align with TypeScript.

/** A class that does something. */
 class SomeClass extends SomeBaseClass {
@@ -2701,7 +2874,11 @@ class SomeClass extends SomeBaseClass {
    */
   someMethod(obj, obviousOtherClass) { ... }
 
-  /** @override */
+  /**
+   * @param {string} param
+   * @return {string}
+   * @override
+   */
   overriddenMethod(param) { ... }
 }
 
@@ -2740,7 +2917,9 @@ class MyClass {
   /** @return {string} */ foo() {...}
 }
 
-/** Function description. */ bar() {...}
+/** No function description allowed inline here. */ function bar() {...}
+
+function /** Function description is also illegal here. */ baz() {...}
 
@@ -2795,8 +2974,8 @@ MyClass.RETRY_COUNT = 33;

7.10 Type annotations

Type annotations are found on @param, @return, @this, and @type tags, -and optionally on @const, @export, and any visibility tags. Type -annotations attached to JSDoc tags must always be enclosed in braces.

+and optionally on @const, @export, and any visibility tags. Type annotations +attached to JSDoc tags must always be enclosed in braces.

7.10.1 Nullability

@@ -2847,9 +3026,9 @@ const /** ?SomeCamelCaseName */ n = ...;

In cases where the compiler doesn't accurately infer the type of an expression, and the assertion functions in goog.asserts -cannot remedy it , it is possible to -tighten the type by adding a type annotation comment and enclosing the -expression in parentheses. Note that the parentheses are required.

+cannot remedy it, it is +possible to tighten the type by adding a type annotation comment and enclosing +the expression in parentheses. Note that the parentheses are required.

/** @type {number} */ (x)
 
@@ -2975,9 +3154,9 @@ annotations.

7.11 Visibility annotations

Visibility annotations (@private, @package, @protected) may be specified -in a @fileoverview block, or on any exported symbol or property. Do not +in a @fileoverview block, or on any exported symbol or property. Do not specify visibility for local variables, whether within a function or at the top -level of a module. All @private names must end with an underscore.

+level of a module. @private names may optionally end with an underscore.

8 Policies

@@ -2992,9 +3171,8 @@ package.

8.2.1 Use a standard warning set

-

-As far as possible projects should use --warning_level=VERBOSE. -

+

As far as possible projects should use +--warning_level=VERBOSE.

8.2.2 How to handle a warning

@@ -3012,14 +3190,17 @@ the situation entirely. the warning is invalid and that the code is actually safe and correct, add a comment to convince the reader of this fact and apply the @suppress annotation. -
  • Otherwise, leave a TODO comment. This is a last resort. If you do -this, do not suppress the warning. The warning should be visible until -it can be taken care of properly.
  • +
  • Otherwise, leave a TODO comment. This is a last resort. + If you do this, do +not suppress the warning. The warning should be visible until it can be +taken care of properly.
  • 8.2.3 Suppress a warning at the narrowest reasonable scope

    -

    Warnings are suppressed at the narrowest reasonable scope, usually that of a single local variable or very small method. Often a variable or method is extracted for that reason alone.

    +

    Warnings are suppressed at the narrowest reasonable scope, usually that of a +single local variable or very small method. Often a variable or method is +extracted for that reason alone.

    Example

    @@ -3052,9 +3233,9 @@ for any other reason.

    1. It is not required to change all existing code to meet current style -guidelines. Reformatting existing code is a trade-off between code churn -and consistency. Style rules evolve over time and these kinds of tweaks to -maintain compliance would create unnecessary churn. However, if significant +guidelines. Reformatting existing code is a trade-off between code churn and +consistency. Style rules evolve over time and these kinds of tweaks to +maintain compliance would create unnecessary churn. However, if significant changes are being made to a file it is expected that the file will be in Google Style.
    2. Be careful not to allow opportunistic style fixes to muddle the focus of a @@ -3095,26 +3276,22 @@ to avoid conflicts with hand-written identifiers.

      9.1 JSDoc tag reference

      -

      JSDoc serves multiple purposes in JavaScript. In addition to being used to -generate documentation it is also used to control tooling. The best known are +

      JSDoc serves multiple purposes in JavaScript. In addition to being used to +generate documentation it is also used to control tooling. The best known are the Closure Compiler type annotations.

      9.1.1 Type annotations and other Closure Compiler annotations

      Documentation for JSDoc used by the Closure Compiler is described in -Annotating JavaScript for the Closure Compiler and Types in the Closure Type -System.

      +Annotating JavaScript for the Closure Compiler and +Types in the Closure Type System.

      9.1.2 Documentation annotations

      -

      In addition to the JSDoc described in Annotating JavaScript for the Closure -Compiler the following tags are common and well supported by various -documentation generation tools (such as JsDossier) for purely documentation -purposes.

      - -

      You may also see other types of JSDoc annotations in third-party code. These -annotations appear in the JSDoc Toolkit Tag Reference but are not considered -part of valid Google style.

      +

      In addition to the JSDoc described in +Annotating JavaScript for the Closure Compiler the following tags are common +and well supported by various documentation generation tools (such as +JsDossier) for purely documentation purposes.

      @@ -3257,6 +3434,10 @@ class ApplicationEvent {}
      +

      You may also see other types of JSDoc annotations in third-party code. These +annotations appear in the JSDoc Toolkit Tag Reference but are not considered +part of valid Google style.

      +

      9.1.3 Framework specific annotations

      The following annotations are specific to a particular framework.

      @@ -3302,30 +3483,6 @@ class ApplicationEvent {} -
      - -
      - -
      - -
      - -
      - -
      - -
      - -
      - -
      - -
      - -
      - -
      -

      9.2 Commonly misunderstood style rules

      Here is a collection of lesser-known or commonly misunderstood facts about @@ -3341,8 +3498,8 @@ class (??).

    3. (??).
    4. The prime directive of line-wrapping is: prefer to break at a higher syntactic level (??).
    5. -
    6. Non-ASCII characters are allowed in string literals, comments and JSDoc, -and in fact are recommended when they make the code easier to read than the +
    7. Non-ASCII characters are allowed in string literals, comments and JSDoc, and +in fact are recommended when they make the code easier to read than the equivalent Unicode escape would (??).
    8. @@ -3352,16 +3509,16 @@ equivalent Unicode escape would (??).

      9.3.1 Closure Compiler

      -

      This program performs type checking and other checks, -optimizations and other transformations (such as ECMAScript 6 to ECMAScript 5 -code lowering).

      +

      This program performs type checking and +other checks, optimizations and other transformations (such as lowering code to +ECMAScript 5).

      9.3.2 clang-format

      This program reformats JavaScript source code into Google Style, and also follows a number of -non-required but frequently readability-enhancing formatting practices. -The output produced by clang-format is compliant with the style guide. +non-required but frequently readability-enhancing formatting practices. The +output produced by clang-format is compliant with the style guide.

      clang-format is not required. Authors are allowed to change its output, and @@ -3371,14 +3528,13 @@ usual way. However, subtrees may choose to opt in to such enforcement locally.9.3.3 Closure compiler linter

      This program checks for a -variety of missteps and anti-patterns. -

      +variety of missteps and anti-patterns.

      9.3.4 Conformance framework

      The JS Conformance Framework is a tool that is part of the Closure Compiler that provides developers a simple means to specify a set of additional checks to be -run against their code base above the standard checks. Conformance checks can, +run against their code base above the standard checks. Conformance checks can, for example, forbid access to a certain property, or calls to a certain function, or missing type information (unknowns).

      @@ -3394,8 +3550,8 @@ globals, which could break the codebase) and security patterns (such as using

      9.4.1 Overview

      This section describes exceptions and additional rules to be followed when -modern ECMAScript 6 syntax is not available to the code authors. Exceptions to -the recommended style are required when ECMAScript 6 syntax is not possible and +modern ECMAScript syntax is not available to the code authors. Exceptions to the +recommended style are required when modern ECMAScript syntax is not possible and are outlined here:

        @@ -3443,8 +3599,8 @@ if that variable is referenced outside the block. For example:

        9.4.2.3 Use @const for constants variables

        For global declarations where the const keyword would be used, if it were -available, annotate the var declaration with @const instead (this is optional -for local variables).

        +available, annotate the var declaration with @const instead (this is +optional for local variables).

        9.4.3 Do not use block scoped functions declarations

        @@ -3457,10 +3613,10 @@ for local variables).

        While most JavaScript VMs implemented before ECMAScript 6 support function declarations within blocks it was not standardized. Implementations were -inconsistent with each other and with the now-standard ECMAScript 6 behavior for -block scoped function declaration. ECMAScript 5 and prior only allow for -function declarations in the root statement list of a script or function and -explicitly ban them in block scopes in strict mode.

        +inconsistent with each other and with the now-standard ECMAScript behavior for +block scoped function declaration. The ECMAScript 5 standard and prior only +allow for function declarations in the root statement list of a script or +function and explicitly ban them in block scopes in strict mode.

        To get consistent behavior, instead use a var initialized with a function expression to define a function within a block:

        @@ -3540,11 +3696,11 @@ goog.provide('foo.bar.method');

        WARNING: goog.scope is deprecated. New files should not use goog.scope even in projects with existing goog.scope usage.

        -

        goog.scope may be used to shorten references to namespaced symbols in -code using goog.provide/goog.require dependency management.

        +

        goog.scope may be used to shorten references to namespaced symbols in code +using goog.provide/goog.require dependency management.

        -

        Only one goog.scope invocation may be added per file. Always place it in -the global scope.

        +

        Only one goog.scope invocation may be added per file. Always place it in the +global scope.

        The opening goog.scope(function() { invocation must be preceded by exactly one blank line and follow any goog.provide statements, goog.require statements, @@ -3566,7 +3722,8 @@ Button = function() { ... }; ...

    -

    Names must be the same as the last property of the global that they are aliasing.

    +

    Names must be the same as the last property of the global that they are +aliasing.

    goog.provide('my.module.SomeType');
     
    @@ -3597,15 +3754,48 @@ circular dependencies between files in the same library. Unlike goog.requi
     a goog.requireType statement is allowed to import a namespace before it is
     defined.

    -

    goog.forwardDeclare may still be used in legacy code to break circular -references spanning across library boundaries, but newer code should be -structured to avoid it.

    -

    goog.forwardDeclare statements must follow the same style rules as goog.require and goog.requireType. The entire block of goog.forwardDeclare, goog.require and goog.requireType statements is sorted alphabetically.

    +

    goog.forwardDeclare is used in legacy code to break circular references +spanning across library boundaries. This pattern however is poorly supported +by build tools and should not be used. Code should be organized to avoid +circular dependencies across libraries (by splitting/merging libraries).

    + +
    9.4.4.4 goog.module.get(name)
    + +

    If a goog.provide file depends on a goog.module file, the goog.provide +file can not normally refer to the module's exports via a global name. Instead, +in addition to goog.require()ing the module, the goog.provide file must +fetch the module's export object by calling goog.module.get('module.name').

    + +

    Note: Only calling goog.module.get('module.name') does not create a build-time +dependency of your code on the module. The goog.require is needed for the +build dependency.

    + +
    9.4.4.5 goog.module.declareLegacyNamespace()
    + +

    WARNING: goog.module.declareLegacyNamespace is only for transitional use.

    + +

    goog.module.declareLegacyNamespace is only for use while migrating a +JavaScript file and its consumers from goog.provide to goog.module +. Update consumers of +your goog.module to use goog.module themselves. +Remove calls to goog.module.declareLegacyNamespace whenever possible. +

    + +

    If you can't update consumers of a legacy namespace from goog.provide to +goog.module soon, please wrap the contents of your file in a call to +goog.scope, use goog.module.get to import the legacy namespace--and then +delete the call to goog.module.declareLegacyNamespace in your goog.module.

    + +

    Calling goog.module.declareLegacyNamespace() inside a goog.module(name) will +declare the module's namespace as a global name just like a goog.provide() +call does. This allows a non goog.module namespace to access the module's +exports without calling goog.module.get(name).

    +