SOL FINAL - Attachment 9 - USPTO JavaScript Coding Standard.pdf
PDF 1 MB Posted
- Attached to
- USPTO Enterprise Cloud Modernization (ECM)
- Solicitation number
- 1333BJ26R00280002
About this file
This is a coding standards document for JavaScript and TypeScript development at the United States Patent and Trademark Office. The document, designated OCIO-STD-010 Version 4.0 (effective September 15, 2025), establishes mandatory coding standards for all JavaScript/TypeScript code delivered by USPTO or contractor staff. The standard is based on the Google JavaScript Style Guide and Google TypeScript Style Guide under CC BY 3.0 licensing, with Version 4.0 incorporating new TypeScript coding standards. The Office of the Chief Information Officer (OCIO), Office of Business Product Delivery Office (BPDO) serves as the office of primary interest, with the Developer Experience Branch handling questions and comments.
The standard covers comprehensive requirements across ten major sections: source file basics (UTF-8 encoding requirements), source file structure (copyright information, JSDoc organization, ES6 module imports/exports), formatting (brace style, indentation using spaces, 120-character column limit, line-wrapping rules), language features (variable declarations using const and let, array and object literals, class and function declarations), naming conventions (camelCase for identifiers), TypeScript-specific type system rules, toolchain requirements, and comments and documentation standards using JSDoc. Key requirements include mandatory semicolons, K&R style braces, use of named exports over default exports, preference for const declarations, avoidance of the Array constructor, use of arrow functions for callbacks, and structural typing for interfaces. The standard prohibits CommonJS in new code (favoring ES6 modules), namespace declarations, mutable exports, var declarations, and numerous other patterns deemed to reduce code quality or security. The document is Section 508 compliant and intended for USPTO staff and contract developers responsible for JavaScript/TypeScript development.
View the file
Other files
Show all 11
On GovTribe
Work with this file
- Download the original file
- Contacts named in this file
- Similar government files
- Ask GovTribe AI about this file
Text version
USPTO/OCIO
USPTO JavaScript/TypeScript
Coding Standard
OCIO-STD-010
Version 4.0
September 15, 2025
USPTO JavaScript/TypeScript Coding Standard
Version 4.0 2 of 99 9/15/2025
Record of Changes/Version History
Version Number
Date of Change
Sections Affected
Type of Reason(s) for Changes
Draft 3.0 1/10/2019 All • Removed outdated sections from version 2.0
• Adopted a subset of the Google JavaScript Style
Guide under CC BY 3.0
• It includes a smattering of guidelines from the
WordPress JavaScript Coding Standards
3.0 final 3/20/2019 Routing Sheet
Approval Page Reviewer e-signature pages CIO Final Approval signature
Draft 4.0 9/15/2025 All Incorporated TypeScript coding standard https://google.github.io/styleguide/jsguide.html#introduction https://google.github.io/styleguide/jsguide.html#introduction https://google.github.io/styleguide/jsguide.html#introduction https://creativecommons.org/licenses/by/3.0/ https://make.wordpress.org/core/handbook/best-practices/coding-standards/javascript/ https://make.wordpress.org/core/handbook/best-practices/coding-standards/javascript/ https://make.wordpress.org/core/handbook/best-practices/coding-standards/javascript/
Version 4.0 3 of 99 9/15/2025
1 INTRODUCTION
1.1 PURPOSE
1.2 BENEFITS
1.3 SCOPE
1.4 OFFICE OF PRIMARY INTEREST
1.5 INTENDED AUDIENCE
1.6 RELATIONSHIP TO POLICIES AND OTHER STANDARDS
1.7 DOCUMENT CONVENTIONS
1.7.1 Fixed-Width Font
1.7.2 Sample Code
1.8 SECTION 508 COMPLIANCE
2 SOURCE FILE BASICS
2.1 FILE ENCODING: UTF-8
2.1.1 Whitespace characters
2.1.2 Special escape sequences
2.1.3 Non-ASCII characters
3 SOURCE FILE STRUCTURE
3.1 COPYRIGHT INFORMATION
3.2 @FILEOVERVIEW JSDOC
3.3 IMPORTS
3.3.1 Import Paths
3.3.2 Namespace versus named imports
3.3.3 Renaming imports
3.4 EXPORTS
3.4.1 Mutable exports
3.4.2 Export visibility
3.4.3 Container classes
3.5 IMPORT AND EXPORT TYPE (TYPESCRIPT)
3.5.1 Import type
3.5.2 Export type
3.5.3 Use modules not namespaces
4 FORMATTING
4.1 BRACES
4.1.1 Braces are used for all control structures
4.1.2 Nonempty blocks: K&R style
4.1.3 Empty blocks: may be concise
4.2 BLOCK INDENTATION: USE SPACES
4.2.1 Array literals: optionally block-like
4.2.2 Object literals: optionally block-like
4.2.3 Class literals
4.2.4 Function expressions
4.2.5 Switch statements
4.3 STATEMENTS
4.3.1 One statement per line
4.3.2 Semicolons are required
4.4 COLUMN LIMIT: 120
4.5 LINE-WRAPPING
4.5.1 Where to break
4.5.2 Indent continuation lines at least +2 spaces
Version 4.0 4 of 99 9/15/2025
4.6 WHITESPACE
4.6.1 Vertical whitespace
4.6.2 Horizontal whitespace
4.6.3 Function arguments
4.7 GROUPING PARENTHESES: RECOMMENDED
5 LANGUAGE FEATURES
5.1 LOCAL VARIABLE DECLARATIONS
5.1.1 Use const and let
5.2 ARRAY LITERALS
5.2.1 Do not use the Array constructor
5.2.2 Do not define properties on arrays
5.2.3 Using spread syntax
5.2.4 Array destructuring
5.3 OBJECT LITERALS
5.3.1 Do not use the Object constructor
5.3.2 Do not mix quoted and unquoted keys
5.3.3 Iterating objects
5.3.4 Using spread syntax
5.3.5 Computed property names
5.3.6 Method shorthand
5.3.7 Shorthand properties
5.3.8 Object destructuring
5.3.9 Enums
5.4 CLASSES
5.4.1 Class declarations
5.4.2 Class method declarations
5.4.2.1 Overriding toString
5.4.3 Static methods
5.4.3.1 Avoid private static methods
5.4.3.2 Do not rely on dynamic dispatch
5.4.3.3 Avoid static this references
5.4.4 Constructors
5.4.5 Class members
5.4.5.1 Computed properties
5.4.5.2 No #private fields
5.4.5.3 Field initializers
5.4.5.4 Use readonly (TypeScript)
5.4.5.5 Parameter properties (TypeScript)
5.4.5.6 Properties used outside of class lexical scope (TypeScript)
5.4.5.7 Getters and setters (TypeScript)
5.4.5.8 Getters and setters (JavaScript)
5.4.6 Disallowed class patterns
5.4.6.1 Do not manipulate prototypes directly
5.4.7 Visibility (TypeScript)
5.4.8 Old-style class declarations (Javascript)
5.5 FUNCTIONS
5.5.1 Terminology
5.5.2 Prefer function declarations for named functions
5.5.3 Nested functions
5.5.4 Do not use function expressions
5.5.5 Arrow function bodies
5.5.6 Rebinding this
5.5.7 Prefer passing arrow functions as callbacks
Version 4.0 5 of 99 9/15/2025
5.5.8 Arrow functions as properties
5.5.9 Event handlers
5.5.10 Parameter initializers
5.5.11 Prefer rest and spread when appropriate
5.5.12 Formatting functions
5.6 THIS
5.7 PRIMITIVE LITERALS
5.7.1 String literals
5.7.1.1 Use single quotes
5.7.1.2 No line continuations
5.7.1.3 Template literals
5.7.2 Number literals
5.7.3 Type coercion (TypeScript)
5.7.3.1 Implicit coercion
5.8 CONTROL STRUCTURES
5.8.1 Control flow statements and blocks
5.8.1.1 Assignment in control statements
5.8.1.2 Iterating containers
5.8.2 Grouping parentheses
5.8.3 Exception handling
5.8.3.1 Instantiate errors using new
5.8.3.2 Only throw errors
5.8.3.3 Catching and rethrowing
5.8.3.4 Empty catch blocks
5.8.4 Switch statements
5.8.5 Equality checks
5.8.6 Keep try blocks focused
5.8.7 Type and non-nullability assertions (TypeScript)
5.8.7.1 Type assertion syntax
5.8.7.2 Double assertions
5.8.7.3 Type assertions and object literals
5.9 DISALLOWED FEATURES
5.9.1 Wrapper objects for primitive types
5.9.2 Automatic Semicolon Insertion
5.9.3 Debugger statements
5.9.4 With
5.9.5 Dynamic code evaluation
5.9.6 Non-standard features
5.9.7 Modifying built-in objects
5.9.8 Other disallowed features
5.9.9 Const enums (TypeScript)
5.10 DECORATORS (TYPESCRIPT)
6 NAMING
6.1 IDENTIFIERS
6.1.1 Naming style
6.1.2 Descriptive names
6.1.3 Camel case
6.1.4 Dollar sign
6.2 RULES BY IDENTIFIER TYPE
6.2.1 Test names
6.2.2 prefix/suffix
6.2.3 Imports
6.2.4 Constants
Version 4.0 6 of 99 9/15/2025
6.2.5 Aliases
6.2.6 Type parameters (TypeScript)
7 TYPE SYSTEM (TYPESCRIPT)
7.1 TYPE INFERENCE
7.1.1 Return types
7.2 UNDEFINED AND NULL
7.2.1 Nullable/undefined type aliases
7.2.2 Prefer optional over |undefined
7.3 USE STRUCTURAL TYPES
7.4 PREFER INTERFACES OVER TYPE LITERAL ALIASES
7.5 ARRAY<T> TYPE
7.6 INDEXABLE TYPES / INDEX SIGNATURES ({[KEY: STRING]: T})
7.7 MAPPED AND CONDITIONAL TYPES
7.8 ANY TYPE
7.8.1 Providing a more specific type
7.8.2 Using unknown over any
7.9 {} TYPE
7.10 TUPLE TYPES
7.11 WRAPPER TYPES
7.12 RETURN TYPE ONLY GENERICS
8 TOOLCHAIN REQUIREMENTS (TYPESCRIPT)
8.1 TYPESCRIPT COMPILER
8.1.1 @ts-ignore
9 COMMENTS AND DOCUMENTATION
9.0.1 JSDoc versus comments
9.0.2 Multi-line comments
9.1 JSDOC GENERAL FORM
9.2 MARKDOWN
9.3 JSDOC TAGS
9.4 LINE WRAPPING
9.5 DOCUMENT ALL TOP-LEVEL EXPORTS OF MODULES
9.6 CLASS COMMENTS
9.7 METHOD AND FUNCTION COMMENTS
9.8 PARAMETER PROPERTY COMMENTS
9.9 JSDOC TYPE ANNOTATIONS
9.10 MAKE COMMENTS THAT ACTUALLY ADD INFORMATION
9.10.1 Comments when calling a function
9.11 PLACE DOCUMENTATION PRIOR TO DECORATORS
10 REFERENCES
11 APPROVAL SIGNATURE
Version 4.0 7 of 99 9/15/2025
1 Introduction
1.1 Purpose
This document specifies the JavaScript/TypeScript Coding Standard enforced by the United States Patent and Trademark Office. The standard established by this document pertains to the JavaScript/TypeScript Programming Language in lieu of its sibling technologies of HTML and CSS. This standard is not comprehensive and is subject to change over time. Nevertheless, it provides a strong starting point for developing readable and secure code.
1.2 Benefits
Coding standards and guidelines are beneficial for ensuring code quality. Quality code has these fundamental characteristics:
1. Readable/Concise – code is readily understood by other developers by virtue of its clarity and adherence to expected formatting and naming conventions. The logic is largely self-documenting with sporadic comments used to explain less obvious segments of code.
Methods and non-local variables have explanatory comments. Each method has an ideally singular purpose.
2. Correct/Consistent – code works as intended in all reasonable circumstances, including multiple browser environments and preferably under greater-than- normal application demands (e.g. user loads, network delays, etc.).
3. Secure – code is not susceptible to problems that would compromise sensitive data or result in prolonged application failure.
1.3 Scope
Compliance with this standard is required of code delivered for any development project using JavaScript/Typescript, whether produced by USPTO or contractor staff.
1.4 Office of Primary Interest
The USPTO, Office of the Chief Information Officer (OCIO), Office of Business Product Delivery Office (BPDO) is the office of primary interest for this document. Any questions or comments about the content of this document should be addressed to BPDO’s Developer Experience Branch.
Version 4.0 8 of 99 9/15/2025
1.5 Intended Audience
The intended audience for this document is USPTO staff and contract developers who are responsible for JavaScript/TypeScript development.
1.6 Relationship to Policies and Other Standards
This document is the fourth version of the JavaScript/TypeScript standard for the USPTO. It is based on the Google JavaScript Style Guide/Google TypeScript Style Guide under CC BY 3.0.
All additions and changes are noted above in the “Version History” section.
1.7 Document Conventions
1.7.1 Fixed-Width Font
JavaScript/TypeScript keywords, package and class names, and other inline code fragments appear in a fixed-width font to aid in readability.
1.7.2 Sample Code
Sample code appears within text boxes using a fixed-width font. Code is syntax highlighted for easier readability. Sample code is shown within text boxes containing both conformant and non-conformant code; these use a black border but have inline comments like //AVOID to indicate which particular lines do not conform. The conforming code has inline comments like
//PREFERRED.
Some sample code may take liberties with prescribed naming and/or formatting conventions, especially in regards to blank lines and line length, in order to display appropriately within this document.
1.8 Section 508 Compliance
The document has been through the section 508 compliance validation and evaluation. It contains no Section 508 compliance issues.
2 Source file basics
2.1 File encoding: UTF-8
Source files are encoded in UTF-8.
https://google.github.io/styleguide/jsguide.html https://google.github.io/styleguide/tsguide.html https://creativecommons.org/licenses/by/3.0/
Version 4.0 9 of 99 9/15/2025
2.1.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 all other whitespace characters in string literals are escaped.
2.1.2 Special escape sequences
For any character that has a special escape sequence (\', \", \\, \b, \f, \n, \r, \t, \v), that sequence is used rather than the corresponding numeric escape (e.g. \x0a, \u000a, or \u{a}).
Legacy octal escapes are never used.
2.1.3 Non-ASCII characters
For the remaining non-ASCII characters, use the actual Unicode character (e.g. ∞). For non-printable characters, the equivalent hex or Unicode escapes (e.g. \u221e) can be used along with an explanatory comment.
Non-ASCII characters
// PREFERRED
// Perfectly clear, even without a comment.
const units = 'μs';
// Use escapes for non-printable characters.
const output = '\ufeff' + content; // byte order mark
// AVOID
// Hard to read and prone to mistakes, even with the comment.
const units = '\u03bcs'; // Greek letter mu, 's'
// The reader has no idea what this is.
const output = '\ufeff' + content;
3 Source file structure
Version 4.0 10 of 99 9/15/2025
Files consist of the following, in order:
1. Copyright information, if present
2. JSDoc with @fileoverview, if present
3. Imports, if present
4. The file’s implementation
Exactly one blank line separates each section that is present.
3.1 Copyright information
If license or copyright information is necessary in a file, add it in a JSDoc at the top of the file.
If the work contains source code from open source and the open-source code is used as-is, the licensure and copyright information of the open-source code shall be included for that open-source code. If the work contains source code from open source and the open-source code has been modified, then the licensure and copyright of the open-source code must be complied with and shall be included for that modified open-source code, including any requirement to annotate codes changes. In cases where the licensure requires the sharing of any code changes or modifications to the open-source component(s), the government shall be notified of the intent to use and specific permission to use and contribute those changes must be given before the code may be used.
3.2 @fileoverview JSDoc
A file may have a top-level @fileoverview JSDoc. If present, it may provide a description of the file's content, its uses, or information about its dependencies. Wrapped lines are not indented.
@fileoverview JS Doc
* @fileoverview Description of file. Lorem ipsum dolor sit amet, consectetur
* adipiscing elit, sed do eiusmod tempor incididunt.
3.3 Imports
This standard assumes and prefers ES module (ESM) syntax (import / export) for new code.
While ESModule is the recommended and supported module format, we recognize that some existing packages and build/runtime environments still require CommonJS ( require / module.exports ). CommonJS use is not recommended for new code. If you must use or consume CommonJS packages, clearly document that in the module’s README and prefer to wrap or isolate CommonJS interop at the project boundary so most application code remains ESM.
Version 4.0 11 of 99 9/15/2025
There are four variants of import statements in ES6 and TypeScript:
Import type Example Use for module[module_import] import * as foo from ...'; TypeScript Imports named[destructuring_import] import { SomeThing } from '...'; TypeScript Imports default import SomeThing from '...';
Only for other external code that requires them side-effect import '...';
Only to import libraries for their side-effects on load (such as custom elements)
Imports
// Good: choose between two options as appropriate (see below).
import * as ng from '@angular/core';
import { Foo } from './foo';
// Only when needed: default imports.
import Button from 'Button';
// Sometimes needed to import libraries for their side effects:
import 'jasmine';
import '@polymer/paper-button';
3.3.1 Import Paths
TypeScript code must use paths to import other TypeScript code. Paths may be relative, i.e.
starting with . or .. or rooted at the base directory, e.g. root/path/to/file.
Code should use relative imports (. /foo) rather than absolute imports path/to/foo when referring to files within the same (logical) project as this allows to move the project around without introducing changes in these imports.
Consider limiting the number of parent steps (./../../) as those can make module and path structures hard to understand.
Version 4.0 12 of 99 9/15/2025
Import Paths
// PREFERRED
import { Symbol1 } from 'path/from/root';
import { Symbol2 } from '../parent/file';
import { Symbol3 } from './sibling';
3.3.2 Namespace versus named imports
Both namespace and named imports can be used.
Prefer named imports for symbols used frequently in a file or for symbols that have clear names, for example Jasmine's describe and it. Named imports can be aliased to clearer names as needed with as.
Prefer namespace imports when using many different symbols from large APIs. A namespace import, despite using the * character, is not comparable to a wildcard import as seen in other languages. Instead, namespace imports give a name to all the exports of a module, and each exported symbol from the module becomes a property on the module name. Namespace imports can aid readability for exported symbols that have common names like Model or Controller without the need to declare aliases.
// Bad: overlong import statement of needlessly namespaced names.
import {Item as TableviewItem, Header as TableviewHeader, Row as TableviewRow, Model as TableviewModel, Renderer as TableviewRenderer} from './tableview';
let item: TableviewItem|undefined;
// PREFERRED
// Better: use the module for namespacing.
import * as tableview from './tableview';
let item: tableview.Item|undefined;
// AVOID
import * as testing from './testing';
// Bad: The module name does not improve readability.
Version 4.0 13 of 99 9/15/2025 testing.describe('foo', () => { testing.it('bar', () => { testing.expect(null).toBeNull();
testing.expect(undefined).toBeUndefined();
// PREFERRED
// Better: give local names for these common functions.
import { describe, it, expect } from './testing';
describe('foo', () => { it('bar', () => { expect(null).toBeNull();
expect(undefined).toBeUndefined();
Special case: Apps JSPB protos
Apps JSPB protos must use named imports, even when it leads to long import lines.
This rule exists to aid in build performance and dead code elimination since often .proto files contain many messages that are not all needed together. By leveraging destructured imports the build system can create finer grained dependencies on Apps JSPB messages while preserving the ergonomics of path-based imports.
JSPB Import
// Good: import the exact set of symbols you need from the proto file.
import { Foo, Bar } from './foo.proto';
function copyFooBar(foo: Foo, bar: Bar) {...}
3.3.3 Renaming imports
Code should fix name collisions by using a namespace import or renaming the exports themselves. Code may rename imports (import { SomeThing as SomeOtherThing }) if needed.
Three examples where renaming can be helpful:
• If it's necessary to avoid collisions with other imported symbols.
Version 4.0 14 of 99 9/15/2025
• If the imported symbol name is generated.
• If importing symbols whose names are unclear by themselves, renaming can improve code clarity. For example, when using RxJS the from function might be more readable when renamed to observableFrom.
3.4 Exports
Use named exports in all code:
Exports
// PREFERRED
// Use named exports:
export class Foo { ... }
// AVOID
// Do not use default exports:
export default class Foo { ... } // Bad!
Why?
// AVOID
// Default exports provide no canonical name, which makes central maintenance difficult with relatively little benefit to code owners, including potentially decreased readability:
import Foo from './bar'; // Legal.
import Bar from './bar'; // Also legal.
// Named exports have the benefit of erroring when import statements try to import something that hasn't been declared. In foo.ts:
const foo = 'blah';
export default foo;
// And in bar.ts
Version 4.0 15 of 99 9/15/2025 import {fizz} from './foo';
// Results in error TS2614: Module '"./foo"' has no exported member 'fizz'. While bar.ts:
import fizz from './foo';
// Results in fizz === foo, which is probably unexpected and difficult to debug.
// Additionally, default exports encourage people to put everything into one big object to namespace it all together:
export default class Foo { static SOME_CONSTANT = ...
static someHelpfulFunction() { ... }
With the above pattern, we have file scope, which can be used as a namespace. We also have a perhaps needless second scope (the class Foo) that can be ambiguously used as both a type and a value in other files.
Instead, prefer use of file scope for namespacing, as well as named exports:
export const SOME_CONSTANT = ...
export function someHelpfulFunction() export class Foo { // only class stuff here
3.4.1 Mutable exports
Regardless of technical support, mutable exports can create hard to understand and debug code, in particular with re-exports across multiple modules. One way to paraphrase this style point is that export let is not allowed.
Mutable exports export let foo = 3;
// In pure ES6, foo is mutable and importers will observe the value change after a second.
// In TS, if foo is re-exported by a second file, importers will not see the value change.
Version 4.0 16 of 99 9/15/2025 window.setTimeout(() => { foo = 4;
}, 1000 /* ms */);
If one needs to support externally accessible and mutable bindings, they should instead use explicit getter functions.
let foo = 3;
window.setTimeout(() => { foo = 4;
}, 1000 /* ms */);
// Use an explicit getter to access the mutable export.
export function getFoo() { return foo; };
For the common pattern of conditionally exporting either of two values, first do the conditional check, then the export. Make sure that all exports are final after the module's body has executed.
Mutable exports
// PREFERRED
function pickApi() { if (useOtherApi()) return OtherApi;
return RegularApi;
export const SomeApi = pickApi();
3.4.2 Export visibility
TypeScript/JavaScript does not support restricting the visibility for exported symbols. Only export symbols that are used outside of the module. Generally minimize the exported API surface of modules.
3.4.3 Container classes
Do not create container classes with static methods or properties for the sake of namespacing.
Instead, export individual constants and functions:
Version 4.0 17 of 99 9/15/2025
Container class
// AVOID
export class Container { static FOO = 1;
static bar() { return 1; }
// PREFERRED
// export individual constants and functions:
export const FOO = 1;
export function bar() { return 1; }
3.5 Import and export type (TypeScript)
3.5.1 Import type
You may use import type {...} when you use the imported symbol only as a type. Use regular imports for values:
Import type import type { Foo } from './foo';
import { Bar } from './foo';
import { type Foo, Bar } from './foo';
The TypeScript compiler automatically handles the distinction and does not insert runtime loads for type references. So why annotate type imports?
The TypeScript compiler can run in 2 modes:
• In development mode, we typically want quick iteration loops. The compiler transpiles to JavaScript without full type information. This is much faster, but requires import type in certain cases.
• In production mode, we want correctness. The compiler type checks everything and ensures import type is used correctly.
Note: If you need to force a runtime load for side effects, use import '...';.
3.5.2 Export type
Version 4.0 18 of 99 9/15/2025
Use export type when re-exporting a type, e.g.:
Export type export type { AnInterface } from './foo';
export type is useful to allow type re-exports in file-by-file transpilation.
export type might also seem useful to avoid ever exporting a value symbol for an API. However it does not give guarantees, either: downstream code might still import an API through a different path. A better way to split & guarantee type vs value usages of an API is to actually split the symbols into e.g. UserService and AjaxUserService. This is less error prone and also better communicates intent.
3.5.3 Use modules not namespaces
TypeScript supports two methods to organize code: namespaces and modules, but namespaces are disallowed. That is, your code must refer to code in other files using imports and exports of the form import { foo } from 'bar';
Your code must not use the namespace Foo { ... } construct. namespaces may only be used when required to interface with external, third party code. To semantically namespace your code, use separate files.
Code must not use require (as in import x = require('...');) for imports. Use ES6 module syntax.
Use modules not namespaces
// Bad: do not use namespaces:
namespace Rocket { function launch() { ... }
// Bad: do not use <reference> /// <reference path="..."/>
// Bad: do not use require() import x = require('mydep');
Version 4.0 19 of 99 9/15/2025
Note: TypeScript namespaces used to be called internal modules and used to use the module keyword in the form module Foo { ... }. Don't use that either. Always use ES6 imports.
4 Formatting
Tip: Consider using clang-format or ESLint to check formatting 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.
4.1 Braces
4.1.1 Braces are used for all control structures
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.
Braces are used for all control structures if (someVeryLongCondition()) doSomething();
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 structure may omit braces and newlines.
Braces are used for all control structures
// EXCEPTION
if (shortCondition()) return;
4.1.2 Nonempty blocks: K&R style
Braces follow the Kernighan and Ritchie style (Egyptian brackets) for nonempty blocks and block-like constructs:
• No line break before the opening brace.
• Line break after the opening brace.
• Line break before the closing brace.
Version 4.0 20 of 99 9/15/2025
• 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.
Nonempty blocks: K&R style
// EXAMPLE
class InnerClass { constructor() {} method(foo) { if (condition(foo)) { try {
// Note: this might fail.
something();
catch (err) { recover();
4.1.3 Empty blocks: may be concise
An empty block or block-like construct may be closed immediately after it is opened, with no characters, space, or line break in between (i.e. {}), unless it is a part of a multi- block statement (one that directly contains multiple blocks: if/else or try/catch/finally). The empty block for a multi-block statement must contain a comment.
Version 4.0 21 of 99 9/15/2025
Empty blocks: may be concise
// EXAMPLE
function doNothing() {} try {
} catch (e) { // catch me
// AVOID
if (condition) {
} else if (otherCondition) {} else { try {
} catch (e) {}
4.2 Block indentation: use spaces
Each time a new block or block-like construct is opened, the indent increases by at least +2 spaces. Use the indentation spacing consistently. 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 Section 4.1.2).
4.2.1 Array literals: optionally block-like
Any array literal may optionally be formatted as if it were a “block-like construct.” For example, the following are all valid (not an exhaustive list):
Version 4.0 22 of 99 9/15/2025
Array literals: optionally block-like
// EXAMPLE
const a = [ 0, 1, 2, const b = [0, 1, 2];
const c = [0, 1, 2];
someMethod(foo, [ 0, 1, 2, ], bar);
Other combinations are allowed, particularly when emphasizing semantic groupings between elements, but should not be used only to reduce the vertical size of larger arrays.
4.2.2 Object literals: optionally block-like
Any object literal may optionally be formatted as if it were a “block-like construct.” The same examples apply as in Section 4.2.1. For example, the following are all valid (not an exhaustive list):
Object literals: optionally block-like const a = { a: 0, b: 1, const b = {a: 0, b: 1};
const c = {a: 0, b: 1};
someMethod(foo, { a: 0, b: 1, }, bar);
4.2.3 Class literals
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
Version 4.0 23 of 99 9/15/2025 assignments - that contain class expressions are still terminated with a semicolon). For inheritance, the extends keyword is sufficient unless the superclass is templatized.
Class literals class Foo { constructor(x) { this.x = x;
class Bar extends Foo { constructor() { super(42);
exports.Baz = class extends Bar { /** @return {number} */ method() { return this.x;
4.2.4 Function expressions
When declaring an anonymous function in the list of arguments for a function call, the body of the function is indented more than the preceding indentation depth using spaces.
Version 4.0 24 of 99 9/15/2025
Function expressions
// EXAMPLE:
prefix.something.reallyLongFunctionName('whatever', (a1, a2) => {
// Indent the function body relative to indentation depth // of the 'prefix' statement one line above.
if (a1.equals(a2)) { someOtherLongFunctionName(a1);
} else { andNowForSomethingCompletelyDifferent(a2.parrot);
some.reallyLongFunctionCall(arg1, arg2, arg3) .thatsWrapped() .then((result) => { // Indent the function body relative to the indentation depth // of the '.then()' call.
if (result) { result.use();
4.2.5 Switch statements
As with any other block, the contents of a switch block are indented using spaces.
After a switch label, a newline appears, and the indentation level is increased using spaces, exactly as if a block were being opened. An explicit block may be used if required by lexical scoping. The following switch label returns to the previous indentation level, as if a block had been closed.
Use a break for each case other than default. When allowing statements to “fall through,” note that explicitly. A blank line is optional between a break and the following case.
Switch statements
// EXAMPLE:
switch (animal) { case Animal.BANDERSNATCH:
handleBandersnatch();
break;
case Animal.JABBERWOCK:
handleJabberwock();
break;
default:
throw new Error('Unknown animal');
Version 4.0 25 of 99 9/15/2025
Switch statements
4.3 Statements
4.3.1 One statement per line
Each statement is followed by a line-break.
4.3.2 Semicolons are required
Every statement must be terminated with a semicolon. Relying on automatic semicolon insertion is forbidden.
4.4 Column limit: 120
JavaScrip/TypeScript code should usually not exceed a column limit of 120 characters. Except as noted below, any line that would exceed this limit must be line-wrapped, as explained in Section
4.5 Line-wrapping below.
Exceptions:
1. ES module import and export from statements.
2. Lines where obeying the column limit is not possible or would hinder discoverability.
Examples include:
• A long URL which should be clickable in source.
• A shell command intended to be copied-and-pasted.
• A long string literal which may need to be copied or searched for wholly (e.g., a long file path).
4.5 Line-wrapping
Terminology Note: Line-wrapping is defined as breaking a single expression into multiple lines.
There is no comprehensive, deterministic formula showing exactly how to line-wrap in every situation. Very often there are several valid ways to line-wrap the same piece of code.
Note: While the typical reason for line-wrapping is to avoid overflowing the column limit, even code that would in fact fit within the column limit may be line-wrapped at the author's discretion.
Tip: Extracting a method or local variable may solve the problem without the need to line-wrap.
Version 4.0 26 of 99 9/15/2025
4.5.1 Where to break
The prime directive of line-wrapping is: prefer to break at a higher syntactic level.
Where to break
// PREFERRED:
currentEstimate = calc(currentEstimate + x * currentEstimate) /
2.0f;
// AVOID:
currentEstimate = calc(currentEstimate + x * currentEstimate) / 2.0f;
In the preceding example, the syntactic levels from highest to lowest are as follows: assignment, division, function call, parameters, number constant.
Operators are wrapped as follows:
1. When a line is broken at an operator the break comes after the symbol.
a. This does not apply to the dot (.), which is not actually an operator.
2. A method or constructor name stays attached to the open parenthesis (() that follows it.
3. A comma (,) stays attached to the token that precedes it.
Note: The primary goal for line wrapping is to have clear code, not necessarily code that fits in the smallest number of lines.
4.5.2 Indent continuation lines at least +2 spaces
When line-wrapping, each line after the first (each continuation line) is indented at least +2 from the original line, unless it falls under the rules of block indentation.
When there are multiple continuation lines, indentation may be varied beyond +2 as appropriate.
In general, continuation lines at a deeper syntactic level are indented by larger multiples of 2, and two lines use the same indentation level if and only if they begin with syntactically parallel elements.
4.6 Whitespace
4.6.1 Vertical whitespace
Version 4.0 27 of 99 9/15/2025
A single blank line appears:
1. Between consecutive methods in a class or object literal
a. 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.
2. Within method bodies, sparingly to create logical groupings of statements. Blank lines at the start or end of a function body are not allowed.
3. Optionally before the first or after the last method in a class or object literal (neither encouraged nor discouraged).
4. As required by other sections of this document.
Multiple consecutive blank lines are permitted, but never required (nor encouraged).
4.6.2 Horizontal whitespace
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.
Beyond where required by the language or other style rules, and apart from literals, and comments, a single internal ASCII space also appears in the following places only.
1. Separating any reserved word (such as if, for, or catch) from an open parenthesis (() that follows it on that line.
2. Separating any reserved word (such as else or catch) from a closing curly brace (}) that precedes it on that line.
3. Before any open curly brace ({), with two exceptions:
a. Before an object literal that is the first argument of a function or the first element in an array literal (e.g. foo({a: [{c: d}]})).
b. In a template expansion, as it is forbidden by the language (e.g. abc${1 + 2}def).
4. On both sides of any binary or ternary operator.
5. After a comma (,) or semicolon (;). Note that spaces are never allowed before these characters.
6. After the colon (:) in an object literal.
Version 4.0 28 of 99 9/15/2025
7. After the slash-asterisk (/*) or the double slash (//) that begins a block comment.
8. On both sides of the double slash (//) that begins an end-of-line comment. Here, multiple spaces are allowed, but not required.
4.6.3 Function arguments
Prefer to put all function arguments on the same line as the function name. If doing so would exceed the 120-column limit, the arguments must be line-wrapped in a readable way. To save space, you may wrap as close to 120 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:
Function arguments
// Arguments start on a new line, indented using spaces. Preferred when the // arguments don't fit on the same line with the function name (or the keyword // "function") but fit entirely on the second line. Works with very long // function names, survives renaming without reindenting, low on space.
doSomething( descriptiveArgumentOne, descriptiveArgumentTwo, descriptiveArgumentThree) {
// If the argument list is longer, wrap at 120. Uses less vertical space, // but violates the rectangle rule and is thus not recommended.
doSomething(veryDescriptiveArgumentNumberOne, veryDescriptiveArgumentTwo, tableModelEventHandlerProxy, artichokeDescriptorAdapterIterator) {
// Two-space, one argument per line. Works with long function names, // survives renaming, and emphasizes each argument.
doSomething( veryDescriptiveArgumentNumberOne, veryDescriptiveArgumentTwo, tableModelEventHandlerProxy, artichokeDescriptorAdapterIterator) {
Version 4.0 29 of 99 9/15/2025
4.7 Grouping parentheses: recommended
Optional grouping parentheses are omitted only when the author and reviewer agree that there is no reasonable chance that the code will be misinterpreted without them, nor would they have made the code easier to read. It is not reasonable to assume that every reader has the entire operator precedence table memorized.
Do not use unnecessary parentheses around the entire expression following delete, typeof, void, return, throw, case, in, of, or yield.In cases where type-checking doesn't accurately infer the type of an expression, it is possible to add a type cast comment by adding a type annotation comment and enclosing the expression in parentheses. The parentheses are required.
/** @type {number} */ (x)
5 Language features
This section delineates which features may or may not be used, and any additional constraints on their use.
5.1 Local variable declarations
5.1.1 Use const and let
Always use const or let to declare variables. Use const by default, unless a variable needs to be reassigned. Never use var.
Use const and let const foo = otherValue; // Use if "foo" never changes.
let bar = someValue; // Use if "bar" is ever assigned into later on.
const and let are block scoped, like variables in most other languages. var in JavaScript is function scoped, which can cause difficult to understand bugs. Don't use it.
Don’t use var
// ILLEGAL:
var foo = someValue; // Don't use - var scoping is complex and causes bugs.
Variables must not be used before their declaration.
Version 4.0 30 of 99 9/15/2025
5.1.2 One variable per declaration
Every local variable declaration declares only one variable: declarations such as let a = 1, b = 2; are not used.
5.2 Array literals
5.2.1 Do not use the Array constructor
Do not use the Array() constructor, with or without new. It has confusing and contradictory usage:
Do not use the variadic array constructor const a = new Array(2); // [undefined, undefined] const b = new Array(2, 3); // [2, 3];
// EXAMPLE:
Instead, always use bracket notation to initialize arrays, or from to initialize an Array with a certain size:
const a = [2];
const b = [2, 3];
// Equivalent to Array(2):
const c = [];
c.length = 2;
// [0, 0, 0, 0, 0]
Array.from<number>({length: 5}).fill(0);
5.2.2 Do not define properties on arrays
Do not define or use non-numeric properties on an array (other than length). Use a Map (or Object) instead.
5.2.3 Using spread syntax
Version 4.0 31 of 99 9/15/2025
Using spread syntax [...foo]; is a convenient shorthand for shallow-copying or concatenating iterables.
Using spread syntax const foo = [ 1, const foo2 = [ ...foo, 6, 7, const foo3 = [ 5, ...foo, foo2[1] === 6;
foo3[1] === 1;
[...foo] // preferred over Array.prototype.slice.call(foo) [...foo, ...bar] // preferred over foo.concat(bar)
When using spread syntax, the value being spread must match what is being created. When creating an array, only spread iterables. Primitives (including null and undefined) must not be spread.
Using spread syntax const foo = [7];
const bar = [5, ...(shouldUseFoo && foo)]; // might be undefined
// Creates {0: 'a', 1: 'b', 2: 'c'} but has no length const fooStrings = ['a', 'b', 'c'];
const ids = {...fooStrings};
// EXAMPLE:
const foo = shouldUseFoo ? [7] : [];
const bar = [5, ...foo];
const fooStrings = ['a', 'b', 'c'];
const ids = [...fooStrings, 'd', 'e'];
Version 4.0 32 of 99 9/15/2025
5.2.4 Array 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 ... and the variable name). Elements should be omitted if they are unused.
Destructuring const [a, b, c, ...rest] = generateResults();
let [, b,, d] = someArray
Destructuring may also be used for function parameters. Always specify [] as the default value if a destructured array parameter is optional, and provide default values on the left hand side:
function optionalDestructuring([a = 4, b = 2] = []) {
// ILLEGAL:
function badDestructuring([a, b] = [4, 2]) {
Tip: For (un)packing multiple values into a function’s parameter or return, prefer object destructuring to array destructuring when possible, as it allows naming the individual elements and specifying a different type for each.
5.3 Object literals
5.3.1 Do not use the Object constructor
The Object constructor is disallowed. Use an object literal ({} or {a: 0, b: 1, c: 2}) instead.
5.3.2 Do not mix quoted and unquoted keys
Version 4.0 33 of 99 9/15/2025
Object literals may represent either structs (with unquoted keys and/or symbols) or dicts (with quoted and/or computed keys). Do not mix these key types in a single object literal.
Do not mix quoted and unquoted keys width: 42, // struct-style unquoted key 'maxWidth': 43, // dict-style quoted key
/* This also extends to passing the property name to functions, like hasOwnProperty. In particular, doing so will break in compiled code because the compiler cannot rename/obfuscate the string literal.*/
// ILLEGAL:
/** @type {{width: number, maxWidth: (number|undefined)}} */ const o = { width: 42 };
if (o.hasOwnProperty('maxWidth')) {
// best implemented as:
/** @type {{width: number, maxWidth: (number|undefined)}} */ const o = { maxWidth: 42 };
if (o.maxWidth !== null) {
5.3.3 Iterating objects
Iterating objects with for (... in ...) is error prone. It will include enumerable properties from the prototype chain.
Do not use unfiltered for (... in ...) statements:
Version 4.0 34 of 99 9/15/2025
Iterating objects
// AVOID:
for (const x in someObj) { // x could come from some parent prototype!
Either filter values explicitly with an if statement, or use for (... of Object.keys(...)).
Iterating objects for (const x in someObj) { if (!someObj.hasOwnProperty(x)) continue;
// now x was definitely defined on someObj for (const x of Object.keys(someObj)) { // note: for _of_!
// now x was definitely defined on someObj for (const [key, value] of Object.entries(someObj)) { // note: for _of_!
// now key was definitely defined on someObj
5.3.4 Using spread syntax
Using spread syntax {...bar} is a convenient shorthand for creating a shallow copy of an object.
When using spread syntax in object initialization, later values replace earlier values at the same key.
Spread syntax const foo = { num: 1, const foo2 = { ...foo, num: 5, const foo3 = { num: 5, ...foo, foo2.num === 5;
Version 4.0 35 of 99 9/15/2025 foo3.num === 1;
When using spread syntax, the value being spread must match what is being created. That is, when creating an object, only objects may be spread; arrays and primitives (including null and undefined) must not be spread.
const foo = {num: 7};
const bar = {num: 5, ...(shouldUseFoo && foo)}; // might be undefined
// Creates {0: 'a', 1: 'b', 2: 'c'} but has no length const fooStrings = ['a', 'b', 'c'];
const ids = {...fooStrings};
const foo = shouldUseFoo ? [7] : [];
const bar = [5, ...foo];
5.3.5 Computed property names
Computed property names (e.g. {['key' + foo()]: 42}) are allowed, and are considered dict-style (quoted) keys (i.e., must not be mixed with non-quoted keys) unless the computed property is a symbol (e.g. [Symbol.iterator]).
5.3.6 Method shorthand
Methods can be defined on object literals using the method shorthand ({method() {…}}) in place of a colon immediately followed by a function or arrow function literal.
Method shorthand return { stuff: 'candy', method() { return this.stuff; // Returns 'candy'
Version 4.0 36 of 99 9/15/2025
Note that this in a method shorthand or function refers to the object literal itself whereas this in an arrow function refers to the scope outside the object literal.
Method shorthand class { getObjectLiteral() { this.stuff = 'fruit';
return { stuff: 'candy', method: () => this.stuff, // Returns 'fruit'
5.3.7 Shorthand properties
Shorthand properties are allowed on object literals.
Shorthand properties const foo = 1;
const bar = 2;
const obj = { foo, bar, method() { return this.foo + this.bar;
assertEquals(3, obj.method());
5.3.8 Object destructuring
Object destructuring patterns may be used on the left-hand side of an assignment 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 {}.
Version 4.0 37 of 99 9/15/2025
// EXAMPLE:
interface Options { /** The number of times to do something. */ num?: number;
/** A string to do stuff to. */ str?: string;
function destructured({num, str = 'default'}: Options = {}) {}
// ILLEGAL:
function nestedTooDeeply({x: {num, str}}: {x: Options}) {} function nonShorthandProperty({num: a, str: b} = {}) {};
function computedKey({a, b, [a + b]: c}) {};
function nontrivialDefault({num, str}: Options = {num: 42, str: 'default'}) {}
5.3.9 Enums
Enumerations are defined by adding properties 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
* Supported temperature scales.
const TemperatureScale = { CELSIUS: 'celsius', FAHRENHEIT: 'fahrenheit',
* An enum with two options.
const Option = {
/** The option used shall have been the first. */
FIRST_OPTION: 1,
/** The second among two options. */
SECOND_OPTION: 2,
Version 4.0 38 of 99 9/15/2025
Enums
5.4 Classes
5.4.1 Class declarations
Class declarations must not be terminated with semicolons:
Class declarations
// EXAMPLE:
class Foo {
// ILLEGAL:
class Foo { }; // Unnecessary semicolon
In contrast, statements that contain class expressions must be terminated with a semicolon:
Class declarations
// EXAMPLE:
export const Baz = class extends Bar { method(): number { return this.x;
}; // Semicolon here as this is a statement, not a declaration
// ILLEGAL:
exports const Baz = class extends Bar { method(): number { return this.x;
It is neither encouraged nor discouraged to have blank lines separating class declaration braces from other class content:
Version 4.0 39 of 99 9/15/2025
Class declarations
// EXAMPLE:
// No spaces around braces - fine.
class Baz { method(): number { return this.x;
// A single space around both braces - also fine.
class Foo { method(): number { return this.x;
5.4.2 Class method declarations
Class method declarations must not use a semicolon to separate individual method declarations:
Class method declarations
// EXAMPLE:
class Foo { doThing() { console.log("A");
// ILLEGAL:
class Foo { doThing() { console.log("A");
}; // <-- unnecessary
Method declarations should be separated from surrounding code by a single blank line:
Version 4.0 40 of 99 9/15/2025
Class method declarations
// EXAMPLE:
class Foo { doThing() { console.log("A");
getOtherThing(): number { return 4;
// AVOID:
class Foo { doThing() { console.log("A");
getOtherThing(): number { return 4;
5.4.2.1 Overriding toString
The toString method may be overridden, but must always succeed and never have visible side effects.
Tip: Beware, in particular, of calling other methods from toString, since exceptional conditions could lead to infinite loops.
5.4.3 Static methods
5.4.3.1 Avoid private static methods
Where it does not interfere with readability, prefer module-local functions over private static methods.
5.4.3.2 Do not rely on dynamic dispatch
Code should not rely on dynamic dispatch of static methods. Static methods should only be called on the base class itself (which defines it directly). 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.
Version 4.0 41 of 99 9/15/2025
Static methods
// ILLEGAL:
// Context for the examples below (this class is okay by itself) class Base { /** @nocollapse */ static foo() {} class Sub extends Base {}
// Discouraged: don't call static methods dynamically function callFoo(cls: typeof Base) { 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 MyClass { static foo() { return this.staticField;
MyClass.staticField = 1;
5.4.3.3 Avoid static this references
Code must not use this in a static context.
JavaScript/TypeScript allows accessing static fields through this. Different from other languages, static fields are also inherited.
Static methods
// ILLEGAL:
class ShoeStore { static storage: Storage = ...;
static isAvailable(s: Shoe) { // Bad: do not use `this` in a static method.
return this.storage.has(s.id);
class EmptyShoeStore extends ShoeStore { static storage: Storage = EMPTY_STORE; // overrides storage from ShoeStore
Version 4.0 42 of 99 9/15/2025
This code is generally surprising: authors might not expect that static fields can be accessed through the this pointer, and might be surprised to find that they can be overridden - this feature is not commonly used.
This code also encourages an anti-pattern of having substantial static state, which causes problems with testability.
5.4.4 Constructors
Constructor calls must use parentheses, even when no arguments are passed:
Constructors
// ILLEGAL:
const x = new Foo;
// EXAMPLE:
const x = new Foo();
// Omitting parentheses can lead to subtle mistakes. These two lines are not equivalent:
new Foo().Bar();
new Foo.Bar();
It is unnecessary to provide an empty constructor or one that simply delegates into its parent class because ES2015 provides a default class constructor if one is not specified. However constructors with parameter properties, visibility modifiers or parameter decorators should not be omitted even if the body of the constructor is empty.
Constructors
// ILLEGAL:
class UnnecessaryConstructor { constructor() {} class UnnecessaryConstructorOverride extends Base { constructor(value: number) { super(value);
// EXAMPLE:
class DefaultConstructor {
Version 4.0 43 of 99 9/15/2025
Constructors class ParameterProperties { constructor(private myService) {} class ParameterDecorators { constructor(@SideEffectDecorator myService) {} class NoInstantiation { private constructor() {}
The constructor should be separated from surrounding code both above and below by a single blank line:
Constructors
// EXAMPLE:
class Foo { myField = 10;
constructor(priv…
This is the start of the file's text. The full file is on GovTribe.
File details come from the government source that posted it. Updated .