readability-cli 0.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
guides/tsguide.md ADDED
@@ -0,0 +1,3662 @@
1
+ Google TypeScript Style Guide
2
+
3
+
4
+
5
+ # Google TypeScript Style Guide
6
+
7
+ This guide is based on the internal Google TypeScript style guide, but it has
8
+ been slightly adjusted to remove Google-internal sections. Google's internal
9
+ environment has different constraints on TypeScript than you might find outside
10
+ of Google. The advice here is specifically useful for people authoring code they
11
+ intend to import into Google, but otherwise may not apply in your external
12
+ environment.
13
+
14
+ There is no automatic deployment process for this version as it's pushed
15
+ on-demand by volunteers.
16
+
17
+ ## Introduction
18
+
19
+ ### Terminology notes
20
+
21
+ This Style Guide uses [RFC 2119](https://tools.ietf.org/html/rfc2119)
22
+ terminology when using the phrases *must*, *must not*, *should*, *should not*,
23
+ and *may*. The terms *prefer* and *avoid* correspond to *should* and *should
24
+ not*, respectively. Imperative and declarative statements are prescriptive and
25
+ correspond to *must*.
26
+
27
+ ### Guide notes
28
+
29
+ All examples given are **non-normative** and serve only to illustrate the
30
+ normative language of the style guide. That is, while the examples are in Google
31
+ Style, they may not illustrate the *only* stylish way to represent the code.
32
+ Optional formatting choices made in examples must not be enforced as rules.
33
+
34
+ ## Source file basics
35
+
36
+ ### File encoding: UTF-8
37
+
38
+ Source files are encoded in **UTF-8**.
39
+
40
+ #### Whitespace characters
41
+
42
+ Aside from the line terminator sequence, the ASCII horizontal space character
43
+ (0x20) is the only whitespace character that appears anywhere in a source file.
44
+ This implies that all other whitespace characters in string literals are
45
+ escaped.
46
+
47
+ #### Special escape sequences
48
+
49
+ For any character that has a special escape sequence (`\'`, `\"`, `\\`, `\b`,
50
+ `\f`, `\n`, `\r`, `\t`, `\v`), that sequence is used rather than the
51
+ corresponding numeric escape (e.g `\x0a`, `\u000a`, or `\u{a}`). Legacy octal
52
+ escapes are never used.
53
+
54
+ #### Non-ASCII characters
55
+
56
+ For the remaining non-ASCII characters, use the actual Unicode character (e.g.
57
+ `∞`). For non-printable characters, the equivalent hex or Unicode escapes (e.g.
58
+ `\u221e`) can be used along with an explanatory comment.
59
+
60
+ ```
61
+ // Perfectly clear, even without a comment.
62
+ const units = 'μs';
63
+
64
+ // Use escapes for non-printable characters.
65
+ const output = '\ufeff' + content; // byte order mark
66
+ ```
67
+
68
+ ```
69
+ // Hard to read and prone to mistakes, even with the comment.
70
+ const units = '\u03bcs'; // Greek letter mu, 's'
71
+
72
+ // The reader has no idea what this is.
73
+ const output = '\ufeff' + content;
74
+ ```
75
+
76
+ ## Source file structure
77
+
78
+ Files consist of the following, **in order**:
79
+
80
+ 1. Copyright information, if present
81
+ 2. JSDoc with `@fileoverview`, if present
82
+ 3. Imports, if present
83
+ 4. The file’s implementation
84
+
85
+ **Exactly one blank line** separates each section that is present.
86
+
87
+ ### Copyright information
88
+
89
+ If license or copyright information is necessary in a file, add it in a JSDoc at
90
+ the top of the file.
91
+
92
+ ### `@fileoverview` JSDoc
93
+
94
+ A file may have a top-level `@fileoverview` JSDoc. If present, it may provide a
95
+ description of the file's content, its uses, or information about its
96
+ dependencies. Wrapped lines are not indented.
97
+
98
+ Example:
99
+
100
+ ```
101
+ /**
102
+ * @fileoverview Description of file. Lorem ipsum dolor sit amet, consectetur
103
+ * adipiscing elit, sed do eiusmod tempor incididunt.
104
+ */
105
+ ```
106
+
107
+ ### Imports
108
+
109
+ There are four variants of import statements in ES6 and TypeScript:
110
+
111
+ | Import type | Example | Use for |
112
+ | --- | --- | --- |
113
+ | module[module\_import] | `import * as foo from '...';` | TypeScript imports |
114
+ | named[destructuring\_import] | `import {SomeThing} from '...';` | TypeScript imports |
115
+ | default | `import SomeThing from '...';` | Only for other external code that requires them |
116
+ | side-effect | `import '...';` | Only to import libraries for their side-effects on load (such as custom elements) |
117
+
118
+ ```
119
+ // Good: choose between two options as appropriate (see below).
120
+ import * as ng from '@angular/core';
121
+ import {Foo} from './foo';
122
+
123
+ // Only when needed: default imports.
124
+ import Button from 'Button';
125
+
126
+ // Sometimes needed to import libraries for their side effects:
127
+ import 'jasmine';
128
+ import '@polymer/paper-button';
129
+ ```
130
+
131
+ #### Import paths
132
+
133
+ TypeScript code *must* use paths to import other TypeScript code. Paths *may* be
134
+ relative, i.e. starting with `.` or `..`,
135
+ or rooted at the base directory, e.g.
136
+ `root/path/to/file`.
137
+
138
+ Code *should* use relative imports (`./foo`) rather than absolute imports
139
+ `path/to/foo` when referring to files within the same (logical) project as this
140
+ allows to move the project around without introducing changes in these imports.
141
+
142
+ Consider limiting the number of parent steps (`../../../`) as those can make
143
+ module and path structures hard to understand.
144
+
145
+ ```
146
+ import {Symbol1} from 'path/from/root';
147
+ import {Symbol2} from '../parent/file';
148
+ import {Symbol3} from './sibling';
149
+ ```
150
+
151
+ #### Namespace versus named imports
152
+
153
+ Both namespace and named imports can be used.
154
+
155
+ Prefer named imports for symbols used frequently in a file or for symbols that
156
+ have clear names, for example Jasmine's `describe` and `it`. Named imports can
157
+ be aliased to clearer names as needed with `as`.
158
+
159
+ Prefer namespace imports when using many different symbols from large APIs. A
160
+ namespace import, despite using the `*` character, is not comparable to a
161
+ "wildcard" import as seen in other languages. Instead, namespace imports give a
162
+ name to all the exports of a module, and each exported symbol from the module
163
+ becomes a property on the module name. Namespace imports can aid readability for
164
+ exported symbols that have common names like `Model` or `Controller` without the
165
+ need to declare aliases.
166
+
167
+ ```
168
+ // Bad: overlong import statement of needlessly namespaced names.
169
+ import {Item as TableviewItem, Header as TableviewHeader, Row as TableviewRow,
170
+ Model as TableviewModel, Renderer as TableviewRenderer} from './tableview';
171
+
172
+ let item: TableviewItem|undefined;
173
+ ```
174
+
175
+ ```
176
+ // Better: use the module for namespacing.
177
+ import * as tableview from './tableview';
178
+
179
+ let item: tableview.Item|undefined;
180
+ ```
181
+
182
+ ```
183
+ import * as testing from './testing';
184
+
185
+ // Bad: The module name does not improve readability.
186
+ testing.describe('foo', () => {
187
+ testing.it('bar', () => {
188
+ testing.expect(null).toBeNull();
189
+ testing.expect(undefined).toBeUndefined();
190
+ });
191
+ });
192
+ ```
193
+
194
+ ```
195
+ // Better: give local names for these common functions.
196
+ import {describe, it, expect} from './testing';
197
+
198
+ describe('foo', () => {
199
+ it('bar', () => {
200
+ expect(null).toBeNull();
201
+ expect(undefined).toBeUndefined();
202
+ });
203
+ });
204
+ ```
205
+
206
+ ##### Special case: Apps JSPB protos
207
+
208
+ Apps JSPB protos must use named imports, even when it leads to long import
209
+ lines.
210
+
211
+ This rule exists to aid in build performance and dead code elimination since
212
+ often `.proto` files contain many `message`s that are not all needed together.
213
+ By leveraging destructured imports the build system can create finer grained
214
+ dependencies on Apps JSPB messages while preserving the ergonomics of path based
215
+ imports.
216
+
217
+ ```
218
+ // Good: import the exact set of symbols you need from the proto file.
219
+ import {Foo, Bar} from './foo.proto';
220
+
221
+ function copyFooBar(foo: Foo, bar: Bar) {...}
222
+ ```
223
+
224
+ #### Renaming imports
225
+
226
+ Code *should* fix name collisions by using a namespace import or renaming the
227
+ exports themselves. Code *may* rename imports (`import {SomeThing as
228
+ SomeOtherThing}`) if needed.
229
+
230
+ Three examples where renaming can be helpful:
231
+
232
+ 1. If it's necessary to avoid collisions with other imported symbols.
233
+ 2. If the imported symbol name is generated.
234
+ 3. If importing symbols whose names are unclear by themselves, renaming can
235
+ improve code clarity. For example, when using RxJS the `from` function might
236
+ be more readable when renamed to `observableFrom`.
237
+
238
+ ### Exports
239
+
240
+ Use named exports in all code:
241
+
242
+ ```
243
+ // Use named exports:
244
+ export class Foo { ... }
245
+ ```
246
+
247
+ Do not use default exports. This ensures that all imports follow a uniform
248
+ pattern.
249
+
250
+ ```
251
+ // Do not use default exports:
252
+ export default class Foo { ... } // BAD!
253
+ ```
254
+
255
+ Why?
256
+
257
+ Default exports provide no canonical name, which makes central maintenance
258
+ difficult with relatively little benefit to code owners, including potentially
259
+ decreased readability:
260
+
261
+ ```
262
+ import Foo from './bar'; // Legal.
263
+ import Bar from './bar'; // Also legal.
264
+ ```
265
+
266
+ Named exports have the benefit of erroring when import statements try to import
267
+ something that hasn't been declared. In `foo.ts`:
268
+
269
+ ```
270
+ const foo = 'blah';
271
+ export default foo;
272
+ ```
273
+
274
+ And in `bar.ts`:
275
+
276
+ ```
277
+ import {fizz} from './foo';
278
+ ```
279
+
280
+ Results in `error TS2614: Module '"./foo"' has no exported member 'fizz'.` While
281
+ `bar.ts`:
282
+
283
+ ```
284
+ import fizz from './foo';
285
+ ```
286
+
287
+ Results in `fizz === foo`, which is probably unexpected and difficult to debug.
288
+
289
+ Additionally, default exports encourage people to put everything into one big
290
+ object to namespace it all together:
291
+
292
+ ```
293
+ export default class Foo {
294
+ static SOME_CONSTANT = ...
295
+ static someHelpfulFunction() { ... }
296
+ ...
297
+ }
298
+ ```
299
+
300
+ With the above pattern, we have file scope, which can be used as a namespace. We
301
+ also have a perhaps needless second scope (the class `Foo`) that can be
302
+ ambiguously used as both a type and a value in other files.
303
+
304
+ Instead, prefer use of file scope for namespacing, as well as named exports:
305
+
306
+ ```
307
+ export const SOME_CONSTANT = ...
308
+ export function someHelpfulFunction()
309
+ export class Foo {
310
+ // only class stuff here
311
+ }
312
+ ```
313
+
314
+ #### Export visibility
315
+
316
+ TypeScript does not support restricting the visibility for exported symbols.
317
+ Only export symbols that are used outside of the module. Generally minimize the
318
+ exported API surface of modules.
319
+
320
+ #### Mutable exports
321
+
322
+ Regardless of technical support, mutable exports can create hard to understand
323
+ and debug code, in particular with re-exports across multiple modules. One way
324
+ to paraphrase this style point is that `export let` is not allowed.
325
+
326
+ ```
327
+ export let foo = 3;
328
+ // In pure ES6, foo is mutable and importers will observe the value change after a second.
329
+ // In TS, if foo is re-exported by a second file, importers will not see the value change.
330
+ window.setTimeout(() => {
331
+ foo = 4;
332
+ }, 1000 /* ms */);
333
+ ```
334
+
335
+ If one needs to support externally accessible and mutable bindings, they
336
+ *should* instead use explicit getter functions.
337
+
338
+ ```
339
+ let foo = 3;
340
+ window.setTimeout(() => {
341
+ foo = 4;
342
+ }, 1000 /* ms */);
343
+ // Use an explicit getter to access the mutable export.
344
+ export function getFoo() { return foo; };
345
+ ```
346
+
347
+ For the common pattern of conditionally exporting either of two values, first do
348
+ the conditional check, then the export. Make sure that all exports are final
349
+ after the module's body has executed.
350
+
351
+ ```
352
+ function pickApi() {
353
+ if (useOtherApi()) return OtherApi;
354
+ return RegularApi;
355
+ }
356
+ export const SomeApi = pickApi();
357
+ ```
358
+
359
+ #### Container classes
360
+
361
+ Do not create container classes with static methods or properties for the sake
362
+ of namespacing.
363
+
364
+ ```
365
+ export class Container {
366
+ static FOO = 1;
367
+ static bar() { return 1; }
368
+ }
369
+ ```
370
+
371
+ Instead, export individual constants and functions:
372
+
373
+ ```
374
+ export const FOO = 1;
375
+ export function bar() { return 1; }
376
+ ```
377
+
378
+ ### Import and export type
379
+
380
+ #### Import type
381
+
382
+ You may use `import type {...}` when you use the imported symbol only as a type.
383
+ Use regular imports for values:
384
+
385
+ ```
386
+ import type {Foo} from './foo';
387
+ import {Bar} from './foo';
388
+
389
+ import {type Foo, Bar} from './foo';
390
+ ```
391
+
392
+ Why?
393
+
394
+ The TypeScript compiler automatically handles the distinction and does not
395
+ insert runtime loads for type references. So why annotate type imports?
396
+
397
+ The TypeScript compiler can run in 2 modes:
398
+
399
+ * In development mode, we typically want quick iteration loops. The compiler
400
+ transpiles to JavaScript without full type information. This is much faster,
401
+ but requires `import type` in certain cases.
402
+ * In production mode, we want correctness. The compiler type checks everything
403
+ and ensures `import type` is used correctly.
404
+
405
+ Note: If you need to force a runtime load for side effects, use `import '...';`.
406
+ See
407
+
408
+ #### Export type
409
+
410
+ Use `export type` when re-exporting a type, e.g.:
411
+
412
+ ```
413
+ export type {AnInterface} from './foo';
414
+ ```
415
+
416
+ Why?
417
+
418
+ `export type` is useful to allow type re-exports in file-by-file transpilation.
419
+ See
420
+ [`isolatedModules` docs](https://www.typescriptlang.org/tsconfig#exports-of-non-value-identifiers).
421
+
422
+ `export type` might also seem useful to avoid ever exporting a value symbol for
423
+ an API. However it does not give guarantees, either: downstream code might still
424
+ import an API through a different path. A better way to split & guarantee type
425
+ vs value usages of an API is to actually split the symbols into e.g.
426
+ `UserService` and `AjaxUserService`. This is less error prone and also better
427
+ communicates intent.
428
+
429
+ #### Use modules not namespaces
430
+
431
+ TypeScript supports two methods to organize code: *namespaces* and *modules*,
432
+ but namespaces are disallowed. That
433
+ is, your code *must* refer to code in other files using imports and exports of
434
+ the form `import {foo} from 'bar';`
435
+
436
+ Your code *must not* use the `namespace Foo { ... }` construct. `namespace`s
437
+ *may* only be used when required to interface with external, third party code.
438
+ To semantically namespace your code, use separate files.
439
+
440
+ Code *must not* use `require` (as in `import x = require('...');`) for imports.
441
+ Use ES6 module syntax.
442
+
443
+ ```
444
+ // Bad: do not use namespaces:
445
+ namespace Rocket {
446
+ function launch() { ... }
447
+ }
448
+
449
+ // Bad: do not use <reference>
450
+ /// <reference path="..."/>
451
+
452
+ // Bad: do not use require()
453
+ import x = require('mydep');
454
+ ```
455
+
456
+ > NB: TypeScript `namespace`s used to be called internal modules and used to use
457
+ > the `module` keyword in the form `module Foo { ... }`. Don't use that either.
458
+ > Always use ES6 imports.
459
+
460
+ ## Language features
461
+
462
+ This section delineates which features may or may not be used, and any
463
+ additional constraints on their use.
464
+
465
+ Language features which are not discussed in this style guide *may* be used with
466
+ no recommendations of their usage.
467
+
468
+ ### Local variable declarations
469
+
470
+ #### Use const and let
471
+
472
+ Always use `const` or `let` to declare variables. Use `const` by default, unless
473
+ a variable needs to be reassigned. Never use `var`.
474
+
475
+ ```
476
+ const foo = otherValue; // Use if "foo" never changes.
477
+ let bar = someValue; // Use if "bar" is ever assigned into later on.
478
+ ```
479
+
480
+ `const` and `let` are block scoped, like variables in most other languages.
481
+ `var` in JavaScript is function scoped, which can cause difficult to understand
482
+ bugs. Don't use it.
483
+
484
+ ```
485
+ var foo = someValue; // Don't use - var scoping is complex and causes bugs.
486
+ ```
487
+
488
+ Variables *must not* be used before their declaration.
489
+
490
+ #### One variable per declaration
491
+
492
+ Every local variable declaration declares only one variable: declarations such
493
+ as `let a = 1, b = 2;` are not used.
494
+
495
+ ### Array literals
496
+
497
+ #### Do not use the `Array` constructor
498
+
499
+ *Do not* use the `Array()` constructor, with or without `new`. It has confusing
500
+ and contradictory usage:
501
+
502
+ ```
503
+ const a = new Array(2); // [undefined, undefined]
504
+ const b = new Array(2, 3); // [2, 3];
505
+ ```
506
+
507
+ Instead, always use bracket notation to initialize arrays, or `from` to
508
+ initialize an `Array` with a certain size:
509
+
510
+ ```
511
+ const a = [2];
512
+ const b = [2, 3];
513
+
514
+ // Equivalent to Array(2):
515
+ const c = [];
516
+ c.length = 2;
517
+
518
+ // [0, 0, 0, 0, 0]
519
+ Array.from<number>({length: 5}).fill(0);
520
+ ```
521
+
522
+ #### Do not define properties on arrays
523
+
524
+ Do not define or use non-numeric properties on an array (other than `length`).
525
+ Use a `Map` (or `Object`) instead.
526
+
527
+ #### Using spread syntax
528
+
529
+ Using spread syntax `[...foo];` is a convenient shorthand for shallow-copying or
530
+ concatenating iterables.
531
+
532
+ ```
533
+ const foo = [
534
+ 1,
535
+ ];
536
+
537
+ const foo2 = [
538
+ ...foo,
539
+ 6,
540
+ 7,
541
+ ];
542
+
543
+ const foo3 = [
544
+ 5,
545
+ ...foo,
546
+ ];
547
+
548
+ foo2[1] === 6;
549
+ foo3[1] === 1;
550
+ ```
551
+
552
+ When using spread syntax, the value being spread *must* match what is being
553
+ created. When creating an array, only spread iterables. Primitives (including
554
+ `null` and `undefined`) *must not* be spread.
555
+
556
+ ```
557
+ const foo = [7];
558
+ const bar = [5, ...(shouldUseFoo && foo)]; // might be undefined
559
+
560
+ // Creates {0: 'a', 1: 'b', 2: 'c'} but has no length
561
+ const fooStrings = ['a', 'b', 'c'];
562
+ const ids = {...fooStrings};
563
+ ```
564
+
565
+ ```
566
+ const foo = shouldUseFoo ? [7] : [];
567
+ const bar = [5, ...foo];
568
+ const fooStrings = ['a', 'b', 'c'];
569
+ const ids = [...fooStrings, 'd', 'e'];
570
+ ```
571
+
572
+ #### Array destructuring
573
+
574
+ Array literals may be used on the left-hand side of an assignment to perform
575
+ destructuring (such as when unpacking multiple values from a single array or
576
+ iterable). A final "rest" element may be included (with no space between the
577
+ `...` and the variable name). Elements should be omitted if they are unused.
578
+
579
+ ```
580
+ const [a, b, c, ...rest] = generateResults();
581
+ let [, b,, d] = someArray;
582
+ ```
583
+
584
+ Destructuring may also be used for function parameters. Always specify `[]` as
585
+ the default value if a destructured array parameter is optional, and provide
586
+ default values on the left hand side:
587
+
588
+ ```
589
+ function destructured([a = 4, b = 2] = []) { … }
590
+ ```
591
+
592
+ Disallowed:
593
+
594
+ ```
595
+ function badDestructuring([a, b] = [4, 2]) { … }
596
+ ```
597
+
598
+ Tip: For (un)packing multiple values into a function’s parameter or return,
599
+ prefer object destructuring to array destructuring when possible, as it allows
600
+ naming the individual elements and specifying a different type for each.
601
+
602
+ ### Object literals
603
+
604
+ #### Do not use the `Object` constructor
605
+
606
+ The `Object` constructor is disallowed. Use an object literal (`{}` or `{a: 0,
607
+ b: 1, c: 2}`) instead.
608
+
609
+ #### Iterating objects
610
+
611
+ Iterating objects with `for (... in ...)` is error prone. It will include
612
+ enumerable properties from the prototype chain.
613
+
614
+ Do not use unfiltered `for (... in ...)` statements:
615
+
616
+ ```
617
+ for (const x in someObj) {
618
+ // x could come from some parent prototype!
619
+ }
620
+ ```
621
+
622
+ Either filter values explicitly with an `if` statement, or use `for (... of
623
+ Object.keys(...))`.
624
+
625
+ ```
626
+ for (const x in someObj) {
627
+ if (!someObj.hasOwnProperty(x)) continue;
628
+ // now x was definitely defined on someObj
629
+ }
630
+ for (const x of Object.keys(someObj)) { // note: for _of_!
631
+ // now x was definitely defined on someObj
632
+ }
633
+ for (const [key, value] of Object.entries(someObj)) { // note: for _of_!
634
+ // now key was definitely defined on someObj
635
+ }
636
+ ```
637
+
638
+ #### Using spread syntax
639
+
640
+ Using spread syntax `{...bar}` is a convenient shorthand for creating a shallow
641
+ copy of an object. When using spread syntax in object initialization, later
642
+ values replace earlier values at the same key.
643
+
644
+ ```
645
+ const foo = {
646
+ num: 1,
647
+ };
648
+
649
+ const foo2 = {
650
+ ...foo,
651
+ num: 5,
652
+ };
653
+
654
+ const foo3 = {
655
+ num: 5,
656
+ ...foo,
657
+ }
658
+
659
+ foo2.num === 5;
660
+ foo3.num === 1;
661
+ ```
662
+
663
+ When using spread syntax, the value being spread *must* match what is being
664
+ created. That is, when creating an object, only objects may be spread; arrays
665
+ and primitives (including `null` and `undefined`) *must not* be spread. Avoid
666
+ spreading objects that have prototypes other than the Object prototype (e.g.
667
+ class definitions, class instances, functions) as the behavior is unintuitive
668
+ (only enumerable non-prototype properties are shallow-copied).
669
+
670
+ ```
671
+ const foo = {num: 7};
672
+ const bar = {num: 5, ...(shouldUseFoo && foo)}; // might be undefined
673
+
674
+ // Creates {0: 'a', 1: 'b', 2: 'c'} but has no length
675
+ const fooStrings = ['a', 'b', 'c'];
676
+ const ids = {...fooStrings};
677
+ ```
678
+
679
+ ```
680
+ const foo = shouldUseFoo ? {num: 7} : {};
681
+ const bar = {num: 5, ...foo};
682
+ ```
683
+
684
+ #### Computed property names
685
+
686
+ Computed property names (e.g. `{['key' + foo()]: 42}`) are allowed, and are
687
+ considered dict-style (quoted) keys (i.e., must not be mixed with non-quoted
688
+ keys) unless the computed property is a
689
+ [symbol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol)
690
+ (e.g. `[Symbol.iterator]`).
691
+
692
+ #### Object destructuring
693
+
694
+ Object destructuring patterns may be used on the left-hand side of an assignment
695
+ to perform destructuring and unpack multiple values from a single object.
696
+
697
+ Destructured objects may also be used as function parameters, but should be kept
698
+ as simple as possible: a single level of unquoted shorthand properties. Deeper
699
+ levels of nesting and computed properties may not be used in parameter
700
+ destructuring. Specify any default values in the left-hand-side of the
701
+ destructured parameter (`{str = 'some default'} = {}`, rather than
702
+ `{str} = {str: 'some default'}`), and if a
703
+ destructured object is itself optional, it must default to `{}`.
704
+
705
+ Example:
706
+
707
+ ```
708
+ interface Options {
709
+ /** The number of times to do something. */
710
+ num?: number;
711
+
712
+ /** A string to do stuff to. */
713
+ str?: string;
714
+ }
715
+
716
+ function destructured({num, str = 'default'}: Options = {}) {}
717
+ ```
718
+
719
+ Disallowed:
720
+
721
+ ```
722
+ function nestedTooDeeply({x: {num, str}}: {x: Options}) {}
723
+ function nontrivialDefault({num, str}: Options = {num: 42, str: 'default'}) {}
724
+ ```
725
+
726
+ ### Classes
727
+
728
+ #### Class declarations
729
+
730
+ Class declarations *must not* be terminated with semicolons:
731
+
732
+ ```
733
+ class Foo {
734
+ }
735
+ ```
736
+
737
+ ```
738
+ class Foo {
739
+ }; // Unnecessary semicolon
740
+ ```
741
+
742
+ In contrast, statements that contain class expressions *must* be terminated with
743
+ a semicolon:
744
+
745
+ ```
746
+ export const Baz = class extends Bar {
747
+ method(): number {
748
+ return this.x;
749
+ }
750
+ }; // Semicolon here as this is a statement, not a declaration
751
+ ```
752
+
753
+ ```
754
+ exports const Baz = class extends Bar {
755
+ method(): number {
756
+ return this.x;
757
+ }
758
+ }
759
+ ```
760
+
761
+ It is neither encouraged nor discouraged to have blank lines separating class
762
+ declaration braces from other class content:
763
+
764
+ ```
765
+ // No spaces around braces - fine.
766
+ class Baz {
767
+ method(): number {
768
+ return this.x;
769
+ }
770
+ }
771
+
772
+ // A single space around both braces - also fine.
773
+ class Foo {
774
+
775
+ method(): number {
776
+ return this.x;
777
+ }
778
+
779
+ }
780
+ ```
781
+
782
+ #### Class method declarations
783
+
784
+ Class method declarations *must not* use a semicolon to separate individual
785
+ method declarations:
786
+
787
+ ```
788
+ class Foo {
789
+ doThing() {
790
+ console.log("A");
791
+ }
792
+ }
793
+ ```
794
+
795
+ ```
796
+ class Foo {
797
+ doThing() {
798
+ console.log("A");
799
+ }; // <-- unnecessary
800
+ }
801
+ ```
802
+
803
+ Method declarations should be separated from surrounding code by a single blank
804
+ line:
805
+
806
+ ```
807
+ class Foo {
808
+ doThing() {
809
+ console.log("A");
810
+ }
811
+
812
+ getOtherThing(): number {
813
+ return 4;
814
+ }
815
+ }
816
+ ```
817
+
818
+ ```
819
+ class Foo {
820
+ doThing() {
821
+ console.log("A");
822
+ }
823
+ getOtherThing(): number {
824
+ return 4;
825
+ }
826
+ }
827
+ ```
828
+
829
+ ##### Overriding toString
830
+
831
+ The `toString` method may be overridden, but must always succeed and never have
832
+ visible side effects.
833
+
834
+ Tip: Beware, in particular, of calling other methods from toString, since
835
+ exceptional conditions could lead to infinite loops.
836
+
837
+ #### Static methods
838
+
839
+ ##### Avoid private static methods
840
+
841
+ Where it does not interfere with readability, prefer module-local functions over
842
+ private static methods.
843
+
844
+ ##### Do not rely on dynamic dispatch
845
+
846
+ Code *should not* rely on dynamic dispatch of static
847
+ methods. Static methods *should* only be called on the base class
848
+ itself (which defines it directly). Static methods *should not* be called on
849
+ variables containing a dynamic instance that may be either the constructor or a
850
+ subclass constructor (and *must* be defined with `@nocollapse` if this is done),
851
+ and *must not* be called directly on a subclass that doesn’t define the method
852
+ itself.
853
+
854
+ Disallowed:
855
+
856
+ ```
857
+ // Context for the examples below (this class is okay by itself)
858
+ class Base {
859
+ /** @nocollapse */ static foo() {}
860
+ }
861
+ class Sub extends Base {}
862
+
863
+ // Discouraged: don't call static methods dynamically
864
+ function callFoo(cls: typeof Base) {
865
+ cls.foo();
866
+ }
867
+
868
+ // Disallowed: don't call static methods on subclasses that don't define it themselves
869
+ Sub.foo();
870
+
871
+ // Disallowed: don't access this in static methods.
872
+ class MyClass {
873
+ static foo() {
874
+ return this.staticField;
875
+ }
876
+ }
877
+ MyClass.staticField = 1;
878
+ ```
879
+
880
+ ##### Avoid static `this` references
881
+
882
+ Code *must not* use `this` in a static context.
883
+
884
+ JavaScript allows accessing static fields through `this`. Different from other
885
+ languages, static fields are also inherited.
886
+
887
+ ```
888
+ class ShoeStore {
889
+ static storage: Storage = ...;
890
+
891
+ static isAvailable(s: Shoe) {
892
+ // Bad: do not use `this` in a static method.
893
+ return this.storage.has(s.id);
894
+ }
895
+ }
896
+
897
+ class EmptyShoeStore extends ShoeStore {
898
+ static storage: Storage = EMPTY_STORE; // overrides storage from ShoeStore
899
+ }
900
+ ```
901
+
902
+ Why?
903
+
904
+ This code is generally surprising: authors might not expect that static fields
905
+ can be accessed through the this pointer, and might be surprised to find that
906
+ they can be overridden - this feature is not commonly used.
907
+
908
+ This code also encourages an anti-pattern of having substantial static state,
909
+ which causes problems with testability.
910
+
911
+ #### Constructors
912
+
913
+ Constructor calls *must* use parentheses, even when no arguments are passed:
914
+
915
+ ```
916
+ const x = new Foo;
917
+ ```
918
+
919
+ ```
920
+ const x = new Foo();
921
+ ```
922
+
923
+ Omitting parentheses can lead to subtle mistakes. These two lines are not
924
+ equivalent:
925
+
926
+ ```
927
+ new Foo().Bar();
928
+ new Foo.Bar();
929
+ ```
930
+
931
+ It is unnecessary to provide an empty constructor or one that simply delegates
932
+ into its parent class because ES2015 provides a default class constructor if one
933
+ is not specified. However constructors with parameter properties, visibility
934
+ modifiers or parameter decorators *should not* be omitted even if the body of
935
+ the constructor is empty.
936
+
937
+ ```
938
+ class UnnecessaryConstructor {
939
+ constructor() {}
940
+ }
941
+ ```
942
+
943
+ ```
944
+ class UnnecessaryConstructorOverride extends Base {
945
+ constructor(value: number) {
946
+ super(value);
947
+ }
948
+ }
949
+ ```
950
+
951
+ ```
952
+ class DefaultConstructor {
953
+ }
954
+
955
+ class ParameterProperties {
956
+ constructor(private myService) {}
957
+ }
958
+
959
+ class ParameterDecorators {
960
+ constructor(@SideEffectDecorator myService) {}
961
+ }
962
+
963
+ class NoInstantiation {
964
+ private constructor() {}
965
+ }
966
+ ```
967
+
968
+ The constructor should be separated from surrounding code both above and below
969
+ by a single blank line:
970
+
971
+ ```
972
+ class Foo {
973
+ myField = 10;
974
+
975
+ constructor(private readonly ctorParam) {}
976
+
977
+ doThing() {
978
+ console.log(ctorParam.getThing() + myField);
979
+ }
980
+ }
981
+ ```
982
+
983
+ ```
984
+ class Foo {
985
+ myField = 10;
986
+ constructor(private readonly ctorParam) {}
987
+ doThing() {
988
+ console.log(ctorParam.getThing() + myField);
989
+ }
990
+ }
991
+ ```
992
+
993
+ #### Class members
994
+
995
+ ##### No #private fields
996
+
997
+ Do not use private fields (also known as private identifiers):
998
+
999
+ ```
1000
+ class Clazz {
1001
+ #ident = 1;
1002
+ }
1003
+ ```
1004
+
1005
+ Instead, use TypeScript's visibility annotations:
1006
+
1007
+ ```
1008
+ class Clazz {
1009
+ private ident = 1;
1010
+ }
1011
+ ```
1012
+
1013
+ Why?
1014
+
1015
+ Private identifiers cause substantial emit size and
1016
+ performance regressions when down-leveled by TypeScript, and are unsupported
1017
+ before ES2015. They can only be downleveled to ES2015, not lower. At the same
1018
+ time, they do not offer substantial benefits when static type checking is used
1019
+ to enforce visibility.
1020
+
1021
+ ##### Use readonly
1022
+
1023
+ Mark properties that are never reassigned outside of the constructor with the
1024
+ `readonly` modifier (these need not be deeply immutable).
1025
+
1026
+ ##### Parameter properties
1027
+
1028
+ Rather than plumbing an obvious initializer through to a class member, use a
1029
+ TypeScript
1030
+ [parameter property](https://www.typescriptlang.org/docs/handbook/2/classes.html#parameter-properties).
1031
+
1032
+ ```
1033
+ class Foo {
1034
+ private readonly barService: BarService;
1035
+
1036
+ constructor(barService: BarService) {
1037
+ this.barService = barService;
1038
+ }
1039
+ }
1040
+ ```
1041
+
1042
+ ```
1043
+ class Foo {
1044
+ constructor(private readonly barService: BarService) {}
1045
+ }
1046
+ ```
1047
+
1048
+ If the parameter property needs documentation,
1049
+ [use an `@param` JSDoc tag](#parameter-property-comments).
1050
+
1051
+ ##### Field initializers
1052
+
1053
+ If a class member is not a parameter, initialize it where it's declared, which
1054
+ sometimes lets you drop the constructor entirely.
1055
+
1056
+ ```
1057
+ class Foo {
1058
+ private readonly userList: string[];
1059
+
1060
+ constructor() {
1061
+ this.userList = [];
1062
+ }
1063
+ }
1064
+ ```
1065
+
1066
+ ```
1067
+ class Foo {
1068
+ private readonly userList: string[] = [];
1069
+ }
1070
+ ```
1071
+
1072
+ Tip: Properties should never be added to or removed from an instance after the
1073
+ constructor is finished, since it significantly hinders VMs’ ability to optimize
1074
+ classes' "shape". Optional fields that may be filled in later should be
1075
+ explicitly initialized to `undefined` to prevent later shape changes.
1076
+
1077
+ ##### Properties used outside of class lexical scope
1078
+
1079
+ Properties used from outside the lexical scope of their containing class, such
1080
+ as an Angular component's properties used from a template, *must not* use
1081
+ `private` visibility, as they are used outside of the lexical scope of their
1082
+ containing class.
1083
+
1084
+ Use either `protected` or `public` as appropriate to the property in question.
1085
+ Angular and AngularJS template properties should use `protected`, but Polymer
1086
+ should use `public`.
1087
+
1088
+ TypeScript code *must not* use `obj['foo']` to bypass the visibility of a
1089
+ property.
1090
+
1091
+ Why?
1092
+
1093
+ When a property is `private`, you are declaring to both automated systems and
1094
+ humans that the property accesses are scoped to the methods of the declaring
1095
+ class, and they will rely on that. For example, a check for unused code will
1096
+ flag a private property that appears to be unused, even if some other file
1097
+ manages to bypass the visibility restriction.
1098
+
1099
+ Though it might appear that `obj['foo']` can bypass visibility in the TypeScript
1100
+ compiler, this pattern can be broken by rearranging the build rules, and also
1101
+ violates [optimization compatibility](#optimization-compatibility).
1102
+
1103
+ ##### Getters and setters
1104
+
1105
+ Getters and setters, also known as accessors, for class members *may* be used.
1106
+ The getter method *must* be a
1107
+ [pure function](https://en.wikipedia.org/wiki/Pure_function) (i.e., result is
1108
+ consistent and has no side effects: getters *must not* change observable state).
1109
+ They are also useful as a means of restricting the visibility of internal or
1110
+ verbose implementation details (shown below).
1111
+
1112
+ ```
1113
+ class Foo {
1114
+ constructor(private readonly someService: SomeService) {}
1115
+
1116
+ get someMember(): string {
1117
+ return this.someService.someVariable;
1118
+ }
1119
+
1120
+ set someMember(newValue: string) {
1121
+ this.someService.someVariable = newValue;
1122
+ }
1123
+ }
1124
+ ```
1125
+
1126
+ ```
1127
+ class Foo {
1128
+ nextId = 0;
1129
+ get next() {
1130
+ return this.nextId++; // Bad: getter changes observable state
1131
+ }
1132
+ }
1133
+ ```
1134
+
1135
+ If an accessor is used to hide a class property, the hidden property *may* be
1136
+ prefixed or suffixed with any whole word, like `internal` or `wrapped`. When
1137
+ using these private properties, access the value through the accessor whenever
1138
+ possible. At least one accessor for a property *must* be non-trivial: do not
1139
+ define "pass-through" accessors only for the purpose of hiding a property.
1140
+ Instead, make the property public (or consider making it `readonly` rather than
1141
+ just defining a getter with no setter).
1142
+
1143
+ ```
1144
+ class Foo {
1145
+ private wrappedBar = '';
1146
+ get bar() {
1147
+ return this.wrappedBar || 'bar';
1148
+ }
1149
+
1150
+ set bar(wrapped: string) {
1151
+ this.wrappedBar = wrapped.trim();
1152
+ }
1153
+ }
1154
+ ```
1155
+
1156
+ ```
1157
+ class Bar {
1158
+ private barInternal = '';
1159
+ // Neither of these accessors have logic, so just make bar public.
1160
+ get bar() {
1161
+ return this.barInternal;
1162
+ }
1163
+
1164
+ set bar(value: string) {
1165
+ this.barInternal = value;
1166
+ }
1167
+ }
1168
+ ```
1169
+
1170
+ Getters and setters *must not* be defined using `Object.defineProperty`, since
1171
+ this interferes with property renaming.
1172
+
1173
+ ##### Computed properties
1174
+
1175
+ Computed properties may only be used in classes when the property is a symbol.
1176
+ Dict-style properties (that is, quoted or computed non-symbol keys) are not
1177
+ allowed (see
1178
+ [rationale for not mixing key types](#features-objects-mixing-keys). A
1179
+ `[Symbol.iterator]` method should be defined for any classes that are logically
1180
+ iterable. Beyond this, `Symbol` should be used sparingly.
1181
+
1182
+ Tip: be careful of using any other built-in symbols (e.g.
1183
+ `Symbol.isConcatSpreadable`) as they are not polyfilled by the compiler and will
1184
+ therefore not work in older browsers.
1185
+
1186
+ #### Visibility
1187
+
1188
+ Restricting visibility of properties, methods, and entire types helps with
1189
+ keeping code decoupled.
1190
+
1191
+ * Limit symbol visibility as much as possible.
1192
+ * Consider converting private methods to non-exported functions within the
1193
+ same file but outside of any class, and moving private properties into a
1194
+ separate, non-exported class.
1195
+ * TypeScript symbols are public by default. Never use the `public` modifier
1196
+ except when declaring non-readonly public parameter properties (in
1197
+ constructors).
1198
+
1199
+ ```
1200
+ class Foo {
1201
+ public bar = new Bar(); // BAD: public modifier not needed
1202
+
1203
+ constructor(public readonly baz: Baz) {} // BAD: readonly implies it's a property which defaults to public
1204
+ }
1205
+ ```
1206
+
1207
+ ```
1208
+ class Foo {
1209
+ bar = new Bar(); // GOOD: public modifier not needed
1210
+
1211
+ constructor(public baz: Baz) {} // public modifier allowed
1212
+ }
1213
+ ```
1214
+
1215
+ See also [export visibility](#export-visibility).
1216
+
1217
+ #### Disallowed class patterns
1218
+
1219
+ ##### Do not manipulate `prototype`s directly
1220
+
1221
+ The `class` keyword allows clearer and more readable class definitions than
1222
+ defining `prototype` properties. Ordinary implementation code has no business
1223
+ manipulating these objects. Mixins and modifying the prototypes of builtin
1224
+ objects are explicitly forbidden.
1225
+
1226
+ **Exception**: Framework code (such as Polymer, or Angular) may need to use `prototype`s, and should not resort
1227
+ to even-worse workarounds to avoid doing so.
1228
+
1229
+ ### Functions
1230
+
1231
+ #### Terminology
1232
+
1233
+ There are many different types of functions, with subtle distinctions between
1234
+ them. This guide uses the following terminology, which aligns with
1235
+ [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions):
1236
+
1237
+ * "function declaration": a declaration (i.e. not an expression) using the
1238
+ `function` keyword
1239
+ * "function expression": an expression, typically used in an assignment or
1240
+ passed as a parameter, using the `function` keyword
1241
+ * "arrow function": an expression using the `=>` syntax
1242
+ * "block body": right hand side of an arrow function with braces
1243
+ * "concise body": right hand side of an arrow function without braces
1244
+
1245
+ Methods and classes/constructors are not covered in this section.
1246
+
1247
+ #### Prefer function declarations for named functions
1248
+
1249
+ Prefer function declarations over arrow functions or function expressions when
1250
+ defining named functions.
1251
+
1252
+ ```
1253
+ function foo() {
1254
+ return 42;
1255
+ }
1256
+ ```
1257
+
1258
+ ```
1259
+ const foo = () => 42;
1260
+ ```
1261
+
1262
+ Arrow functions *may* be used, for example, when an explicit type annotation is
1263
+ required.
1264
+
1265
+ ```
1266
+ interface SearchFunction {
1267
+ (source: string, subString: string): boolean;
1268
+ }
1269
+
1270
+ const fooSearch: SearchFunction = (source, subString) => { ... };
1271
+ ```
1272
+
1273
+ #### Nested functions
1274
+
1275
+ Functions nested within other methods or functions *may* use function
1276
+ declarations or arrow functions, as appropriate. In method bodies in particular,
1277
+ arrow functions are preferred because they have access to the outer `this`.
1278
+
1279
+ #### Do not use function expressions
1280
+
1281
+ Do not use function expressions. Use arrow functions instead.
1282
+
1283
+ ```
1284
+ bar(() => { this.doSomething(); })
1285
+ ```
1286
+
1287
+ ```
1288
+ bar(function() { ... })
1289
+ ```
1290
+
1291
+ **Exception:** Function expressions *may* be used *only if* code has to
1292
+ dynamically rebind `this` (but this is [discouraged](#rebinding-this)), or for
1293
+ generator functions (which do not have an arrow syntax).
1294
+
1295
+ #### Arrow function bodies
1296
+
1297
+ Use arrow functions with concise bodies (i.e. expressions) or block bodies as
1298
+ appropriate.
1299
+
1300
+ ```
1301
+ // Top level functions use function declarations.
1302
+ function someFunction() {
1303
+ // Block bodies are fine:
1304
+ const receipts = books.map((b: Book) => {
1305
+ const receipt = payMoney(b.price);
1306
+ recordTransaction(receipt);
1307
+ return receipt;
1308
+ });
1309
+
1310
+ // Concise bodies are fine, too, if the return value is used:
1311
+ const longThings = myValues.filter(v => v.length > 1000).map(v => String(v));
1312
+
1313
+ function payMoney(amount: number) {
1314
+ // function declarations are fine, but must not access `this`.
1315
+ }
1316
+
1317
+ // Nested arrow functions may be assigned to a const.
1318
+ const computeTax = (amount: number) => amount * 0.12;
1319
+ }
1320
+ ```
1321
+
1322
+ Only use a concise body if the return value of the function is actually used.
1323
+ The block body makes sure the return type is `void` then and prevents potential
1324
+ side effects.
1325
+
1326
+ ```
1327
+ // BAD: use a block body if the return value of the function is not used.
1328
+ myPromise.then(v => console.log(v));
1329
+ // BAD: this typechecks, but the return value still leaks.
1330
+ let f: () => void;
1331
+ f = () => 1;
1332
+ ```
1333
+
1334
+ ```
1335
+ // GOOD: return value is unused, use a block body.
1336
+ myPromise.then(v => {
1337
+ console.log(v);
1338
+ });
1339
+ // GOOD: code may use blocks for readability.
1340
+ const transformed = [1, 2, 3].map(v => {
1341
+ const intermediate = someComplicatedExpr(v);
1342
+ const more = acrossManyLines(intermediate);
1343
+ return worthWrapping(more);
1344
+ });
1345
+ // GOOD: explicit `void` ensures no leaked return value
1346
+ myPromise.then(v => void console.log(v));
1347
+ ```
1348
+
1349
+ Tip: The `void` operator can be used to ensure an arrow function with an
1350
+ expression body returns `undefined` when the result is unused.
1351
+
1352
+ #### Rebinding `this`
1353
+
1354
+ Function expressions and function declarations *must not* use `this` unless they
1355
+ specifically exist to rebind the `this` pointer. Rebinding `this` can in most
1356
+ cases be avoided by using arrow functions or explicit parameters.
1357
+
1358
+ ```
1359
+ function clickHandler() {
1360
+ // Bad: what's `this` in this context?
1361
+ this.textContent = 'Hello';
1362
+ }
1363
+ // Bad: the `this` pointer reference is implicitly set to document.body.
1364
+ document.body.onclick = clickHandler;
1365
+ ```
1366
+
1367
+ ```
1368
+ // Good: explicitly reference the object from an arrow function.
1369
+ document.body.onclick = () => { document.body.textContent = 'hello'; };
1370
+ // Alternatively: take an explicit parameter
1371
+ const setTextFn = (e: HTMLElement) => { e.textContent = 'hello'; };
1372
+ document.body.onclick = setTextFn.bind(null, document.body);
1373
+ ```
1374
+
1375
+ Prefer arrow functions over other approaches to binding `this`, such as
1376
+ `f.bind(this)`, `goog.bind(f, this)`, or `const self = this`.
1377
+
1378
+ #### Prefer passing arrow functions as callbacks
1379
+
1380
+ Callbacks can be invoked with unexpected arguments that can pass a type check
1381
+ but still result in logical errors.
1382
+
1383
+ Avoid passing a named callback to a higher-order function, unless you are sure
1384
+ of the stability of both functions' call signatures. Beware, in particular, of
1385
+ less-commonly-used optional parameters.
1386
+
1387
+ ```
1388
+ // BAD: Arguments are not explicitly passed, leading to unintended behavior
1389
+ // when the optional `radix` argument gets the array indices 0, 1, and 2.
1390
+ const numbers = ['11', '5', '10'].map(parseInt);
1391
+ // > [11, NaN, 2];
1392
+ ```
1393
+
1394
+ Instead, prefer passing an arrow-function that explicitly forwards parameters to
1395
+ the named callback.
1396
+
1397
+ ```
1398
+ // GOOD: Arguments are explicitly passed to the callback
1399
+ const numbers = ['11', '5', '3'].map((n) => parseInt(n));
1400
+ // > [11, 5, 3]
1401
+
1402
+ // GOOD: Function is locally defined and is designed to be used as a callback
1403
+ function dayFilter(element: string|null|undefined) {
1404
+ return element != null && element.endsWith('day');
1405
+ }
1406
+
1407
+ const days = ['tuesday', undefined, 'juice', 'wednesday'].filter(dayFilter);
1408
+ ```
1409
+
1410
+ #### Arrow functions as properties
1411
+
1412
+ Classes usually *should not* contain properties initialized to arrow functions.
1413
+ Arrow function properties require the calling function to understand that the
1414
+ callee's `this` is already bound, which increases confusion about what `this`
1415
+ is, and call sites and references using such handlers look broken (i.e. require
1416
+ non-local knowledge to determine that they are correct). Code *should* always
1417
+ use arrow functions to call instance methods (`const handler = (x) => {
1418
+ this.listener(x); };`), and *should not* obtain or pass references to instance
1419
+ methods (~~`const handler = this.listener; handler(x);`~~).
1420
+
1421
+ > Note: in some specific situations, e.g. when binding functions in a template,
1422
+ > arrow functions as properties are useful and create much more readable code.
1423
+ > Use judgement with this rule. Also, see the
1424
+ > [`Event Handlers`](#event-handlers) section below.
1425
+
1426
+ ```
1427
+ class DelayHandler {
1428
+ constructor() {
1429
+ // Problem: `this` is not preserved in the callback. `this` in the callback
1430
+ // will not be an instance of DelayHandler.
1431
+ setTimeout(this.patienceTracker, 5000);
1432
+ }
1433
+ private patienceTracker() {
1434
+ this.waitedPatiently = true;
1435
+ }
1436
+ }
1437
+ ```
1438
+
1439
+ ```
1440
+ // Arrow functions usually should not be properties.
1441
+ class DelayHandler {
1442
+ constructor() {
1443
+ // Bad: this code looks like it forgot to bind `this`.
1444
+ setTimeout(this.patienceTracker, 5000);
1445
+ }
1446
+ private patienceTracker = () => {
1447
+ this.waitedPatiently = true;
1448
+ }
1449
+ }
1450
+ ```
1451
+
1452
+ ```
1453
+ // Explicitly manage `this` at call time.
1454
+ class DelayHandler {
1455
+ constructor() {
1456
+ // Use anonymous functions if possible.
1457
+ setTimeout(() => {
1458
+ this.patienceTracker();
1459
+ }, 5000);
1460
+ }
1461
+ private patienceTracker() {
1462
+ this.waitedPatiently = true;
1463
+ }
1464
+ }
1465
+ ```
1466
+
1467
+ #### Event handlers
1468
+
1469
+ Event handlers *may* use arrow functions when there is no need to uninstall the
1470
+ handler (for example, if the event is emitted by the class itself). If the
1471
+ handler requires uninstallation, arrow function properties are the right
1472
+ approach, because they automatically capture `this` and provide a stable
1473
+ reference to uninstall.
1474
+
1475
+ ```
1476
+ // Event handlers may be anonymous functions or arrow function properties.
1477
+ class Component {
1478
+ onAttached() {
1479
+ // The event is emitted by this class, no need to uninstall.
1480
+ this.addEventListener('click', () => {
1481
+ this.listener();
1482
+ });
1483
+ // this.listener is a stable reference, we can uninstall it later.
1484
+ window.addEventListener('onbeforeunload', this.listener);
1485
+ }
1486
+ onDetached() {
1487
+ // The event is emitted by window. If we don't uninstall, this.listener will
1488
+ // keep a reference to `this` because it's bound, causing a memory leak.
1489
+ window.removeEventListener('onbeforeunload', this.listener);
1490
+ }
1491
+ // An arrow function stored in a property is bound to `this` automatically.
1492
+ private listener = () => {
1493
+ confirm('Do you want to exit the page?');
1494
+ }
1495
+ }
1496
+ ```
1497
+
1498
+ Do not use `bind` in the expression that installs an event handler, because it
1499
+ creates a temporary reference that can't be uninstalled.
1500
+
1501
+ ```
1502
+ // Binding listeners creates a temporary reference that prevents uninstalling.
1503
+ class Component {
1504
+ onAttached() {
1505
+ // This creates a temporary reference that we won't be able to uninstall
1506
+ window.addEventListener('onbeforeunload', this.listener.bind(this));
1507
+ }
1508
+ onDetached() {
1509
+ // This bind creates a different reference, so this line does nothing.
1510
+ window.removeEventListener('onbeforeunload', this.listener.bind(this));
1511
+ }
1512
+ private listener() {
1513
+ confirm('Do you want to exit the page?');
1514
+ }
1515
+ }
1516
+ ```
1517
+
1518
+ #### Parameter initializers
1519
+
1520
+ Optional function parameters *may* be given a default initializer to use when
1521
+ the argument is omitted. Initializers *must not* have any observable side
1522
+ effects. Initializers *should* be kept as simple as possible.
1523
+
1524
+ ```
1525
+ function process(name: string, extraContext: string[] = []) {}
1526
+ function activate(index = 0) {}
1527
+ ```
1528
+
1529
+ ```
1530
+ // BAD: side effect of incrementing the counter
1531
+ let globalCounter = 0;
1532
+ function newId(index = globalCounter++) {}
1533
+
1534
+ // BAD: exposes shared mutable state, which can introduce unintended coupling
1535
+ // between function calls
1536
+ class Foo {
1537
+ private readonly defaultPaths: string[];
1538
+ frobnicate(paths = defaultPaths) {}
1539
+ }
1540
+ ```
1541
+
1542
+ Use default parameters sparingly. Prefer
1543
+ [destructuring](#features-objects-destructuring) to create readable APIs when
1544
+ there are more than a small handful of optional parameters that do not have a
1545
+ natural order.
1546
+
1547
+ #### Prefer rest and spread when appropriate
1548
+
1549
+ Use a *rest* parameter instead of accessing `arguments`. Never name a local
1550
+ variable or parameter `arguments`, which confusingly shadows the built-in name.
1551
+
1552
+ ```
1553
+ function variadic(array: string[], ...numbers: number[]) {}
1554
+ ```
1555
+
1556
+ Use function spread syntax instead of `Function.prototype.apply`.
1557
+
1558
+ #### Formatting functions
1559
+
1560
+ Blank lines at the start or end of the function body are not allowed.
1561
+
1562
+ A single blank line *may* be used within function bodies sparingly to create
1563
+ *logical groupings* of statements.
1564
+
1565
+ Generators should attach the `*` to the `function` and `yield` keywords, as in
1566
+ `function* foo()` and `yield* iter`, rather than ~~`function *foo()`~~ or
1567
+ ~~`yield *iter`~~.
1568
+
1569
+ Parentheses around the left-hand side of a single-argument arrow function are
1570
+ recommended but not required.
1571
+
1572
+ Do not put a space after the `...` in rest or spread syntax.
1573
+
1574
+ ```
1575
+ function myFunction(...elements: number[]) {}
1576
+ myFunction(...array, ...iterable, ...generator());
1577
+ ```
1578
+
1579
+ ### this
1580
+
1581
+ Only use `this` in class constructors and methods, functions that have an
1582
+ explicit `this` type declared (e.g. `function func(this: ThisType, ...)`), or in
1583
+ arrow functions defined in a scope where `this` may be used.
1584
+
1585
+ Never use `this` to refer to the global object, the context of an `eval`, the
1586
+ target of an event, or unnecessarily `call()`ed or `apply()`ed functions.
1587
+
1588
+ ```
1589
+ this.alert('Hello');
1590
+ ```
1591
+
1592
+ ### Interfaces
1593
+
1594
+ ### Primitive literals
1595
+
1596
+ #### String literals
1597
+
1598
+ ##### Use single quotes
1599
+
1600
+ Ordinary string literals are delimited with single quotes (`'`), rather than
1601
+ double quotes (`"`).
1602
+
1603
+ Tip: if a string contains a single quote character, consider using a template
1604
+ string to avoid having to escape the quote.
1605
+
1606
+ ##### No line continuations
1607
+
1608
+ Do not use *line continuations* (that is, ending a line inside a string literal
1609
+ with a backslash) in either ordinary or template string literals. Even though
1610
+ ES5 allows this, it can lead to tricky errors if any trailing whitespace comes
1611
+ after the slash, and is less obvious to readers.
1612
+
1613
+ Disallowed:
1614
+
1615
+ ```
1616
+ const LONG_STRING = 'This is a very very very very very very very long string. \
1617
+ It inadvertently contains long stretches of spaces due to how the \
1618
+ continued lines are indented.';
1619
+ ```
1620
+
1621
+ Instead, write
1622
+
1623
+ ```
1624
+ const LONG_STRING = 'This is a very very very very very very long string. ' +
1625
+ 'It does not contain long stretches of spaces because it uses ' +
1626
+ 'concatenated strings.';
1627
+ const SINGLE_STRING =
1628
+ 'http://it.is.also/acceptable_to_use_a_single_long_string_when_breaking_would_hinder_search_discoverability';
1629
+ ```
1630
+
1631
+ ##### Template literals
1632
+
1633
+ Use template literals (delimited with `` ` ``) over complex string
1634
+ concatenation, particularly if multiple string literals are involved. Template
1635
+ literals may span multiple lines.
1636
+
1637
+ If a template literal spans multiple lines, it does not need to follow the
1638
+ indentation of the enclosing block, though it may if the added whitespace does
1639
+ not matter.
1640
+
1641
+ Example:
1642
+
1643
+ ```
1644
+ function arithmetic(a: number, b: number) {
1645
+ return `Here is a table of arithmetic operations:
1646
+ ${a} + ${b} = ${a + b}
1647
+ ${a} - ${b} = ${a - b}
1648
+ ${a} * ${b} = ${a * b}
1649
+ ${a} / ${b} = ${a / b}`;
1650
+ }
1651
+ ```
1652
+
1653
+ #### Number literals
1654
+
1655
+ Numbers may be specified in decimal, hex, octal, or binary. Use exactly `0x`,
1656
+ `0o`, and `0b` prefixes, with lowercase letters, for hex, octal, and binary,
1657
+ respectively. Never include a leading zero unless it is immediately followed by
1658
+ `x`, `o`, or `b`.
1659
+
1660
+ #### Type coercion
1661
+
1662
+ TypeScript code *may* use the `String()` and `Boolean()` (note: no `new`!)
1663
+ functions, string template literals, or `!!` to coerce types.
1664
+
1665
+ ```
1666
+ const bool = Boolean(false);
1667
+ const str = String(aNumber);
1668
+ const bool2 = !!str;
1669
+ const str2 = `result: ${bool2}`;
1670
+ ```
1671
+
1672
+ Values of enum types (including unions of enum types and other types) *must not*
1673
+ be converted to booleans with `Boolean()` or `!!`, and must instead be compared
1674
+ explicitly with comparison operators.
1675
+
1676
+ ```
1677
+ enum SupportLevel {
1678
+ NONE,
1679
+ BASIC,
1680
+ ADVANCED,
1681
+ }
1682
+
1683
+ const level: SupportLevel = ...;
1684
+ let enabled = Boolean(level);
1685
+
1686
+ const maybeLevel: SupportLevel|undefined = ...;
1687
+ enabled = !!maybeLevel;
1688
+ ```
1689
+
1690
+ ```
1691
+ enum SupportLevel {
1692
+ NONE,
1693
+ BASIC,
1694
+ ADVANCED,
1695
+ }
1696
+
1697
+ const level: SupportLevel = ...;
1698
+ let enabled = level !== SupportLevel.NONE;
1699
+
1700
+ const maybeLevel: SupportLevel|undefined = ...;
1701
+ enabled = level !== undefined && level !== SupportLevel.NONE;
1702
+ ```
1703
+
1704
+ Why?
1705
+
1706
+ For most purposes, it doesn't matter what number or string value an enum name is
1707
+ mapped to at runtime, because values of enum types are referred to by name in
1708
+ source code. Consequently, engineers are accustomed to not thinking about this,
1709
+ and so situations where it *does* matter are undesirable because they will be
1710
+ surprising. Such is the case with conversion of enums to booleans; in
1711
+ particular, by default, the first declared enum value is falsy (because it is 0)
1712
+ while the others are truthy, which is likely to be unexpected. Readers of code
1713
+ that uses an enum value may not even know whether it's the first declared value
1714
+ or not.
1715
+
1716
+ Using string concatenation to cast to string is discouraged, as we check that
1717
+ operands to the plus operator are of matching types.
1718
+
1719
+ Code *must* use `Number()` to parse numeric values, and *must* check its return
1720
+ for `NaN` values explicitly, unless failing to parse is impossible from context.
1721
+
1722
+ Note: `Number('')`, `Number(' ')`, and `Number('\t')` would return `0` instead
1723
+ of `NaN`. `Number('Infinity')` and `Number('-Infinity')` would return `Infinity`
1724
+ and `-Infinity` respectively. Additionally, exponential notation such as
1725
+ `Number('1e+309')` and `Number('-1e+309')` can overflow into `Infinity`. These
1726
+ cases may require special handling.
1727
+
1728
+ ```
1729
+ const aNumber = Number('123');
1730
+ if (!isFinite(aNumber)) throw new Error(...);
1731
+ ```
1732
+
1733
+ Code *must not* use unary plus (`+`) to coerce strings to numbers. Parsing
1734
+ numbers can fail, has surprising corner cases, and can be a code smell (parsing
1735
+ at the wrong layer). A unary plus is too easy to miss in code reviews given
1736
+ this.
1737
+
1738
+ ```
1739
+ const x = +y;
1740
+ ```
1741
+
1742
+ Code also *must not* use `parseInt` or `parseFloat` to parse numbers, except for
1743
+ non-base-10 strings (see below). Both of those functions ignore trailing
1744
+ characters in the string, which can shadow error conditions (e.g. parsing `12
1745
+ dwarves` as `12`).
1746
+
1747
+ ```
1748
+ const n = parseInt(someString, 10); // Error prone,
1749
+ const f = parseFloat(someString); // regardless of passing a radix.
1750
+ ```
1751
+
1752
+ Code that requires parsing with a radix *must* check that its input contains
1753
+ only appropriate digits for that radix before calling into `parseInt`;
1754
+
1755
+ ```
1756
+ if (!/^[a-fA-F0-9]+$/.test(someString)) throw new Error(...);
1757
+ // Needed to parse hexadecimal.
1758
+ // tslint:disable-next-line:ban
1759
+ const n = parseInt(someString, 16); // Only allowed for radix != 10
1760
+ ```
1761
+
1762
+ Use `Number()` followed by `Math.floor` or `Math.trunc` (where available) to
1763
+ parse integer numbers:
1764
+
1765
+ ```
1766
+ let f = Number(someString);
1767
+ if (isNaN(f)) handleError();
1768
+ f = Math.floor(f);
1769
+ ```
1770
+
1771
+ ##### Implicit coercion
1772
+
1773
+ Do not use explicit boolean coercions in conditional clauses that have implicit
1774
+ boolean coercion. Those are the conditions in an `if`, `for` and `while`
1775
+ statements.
1776
+
1777
+ ```
1778
+ const foo: MyInterface|null = ...;
1779
+ if (!!foo) {...}
1780
+ while (!!foo) {...}
1781
+ ```
1782
+
1783
+ ```
1784
+ const foo: MyInterface|null = ...;
1785
+ if (foo) {...}
1786
+ while (foo) {...}
1787
+ ```
1788
+
1789
+ [As with explicit conversions](#type-coercion), values of enum types (including
1790
+ unions of enum types and other types) *must not* be implicitly coerced to
1791
+ booleans, and must instead be compared explicitly with comparison operators.
1792
+
1793
+ ```
1794
+ enum SupportLevel {
1795
+ NONE,
1796
+ BASIC,
1797
+ ADVANCED,
1798
+ }
1799
+
1800
+ const level: SupportLevel = ...;
1801
+ if (level) {...}
1802
+
1803
+ const maybeLevel: SupportLevel|undefined = ...;
1804
+ if (level) {...}
1805
+ ```
1806
+
1807
+ ```
1808
+ enum SupportLevel {
1809
+ NONE,
1810
+ BASIC,
1811
+ ADVANCED,
1812
+ }
1813
+
1814
+ const level: SupportLevel = ...;
1815
+ if (level !== SupportLevel.NONE) {...}
1816
+
1817
+ const maybeLevel: SupportLevel|undefined = ...;
1818
+ if (level !== undefined && level !== SupportLevel.NONE) {...}
1819
+ ```
1820
+
1821
+ Other types of values may be either implicitly coerced to booleans or compared
1822
+ explicitly with comparison operators:
1823
+
1824
+ ```
1825
+ // Explicitly comparing > 0 is OK:
1826
+ if (arr.length > 0) {...}
1827
+ // so is relying on boolean coercion:
1828
+ if (arr.length) {...}
1829
+ ```
1830
+
1831
+ ### Control structures
1832
+
1833
+ #### Control flow statements and blocks
1834
+
1835
+ Control flow statements (`if`, `else`, `for`, `do`, `while`, etc) always use
1836
+ braced blocks for the containing code, even if the body contains only a single
1837
+ statement. The first statement of a non-empty block must begin on its own line.
1838
+
1839
+ ```
1840
+ for (let i = 0; i < x; i++) {
1841
+ doSomethingWith(i);
1842
+ }
1843
+
1844
+ if (x) {
1845
+ doSomethingWithALongMethodNameThatForcesANewLine(x);
1846
+ }
1847
+ ```
1848
+
1849
+ ```
1850
+ if (x)
1851
+ doSomethingWithALongMethodNameThatForcesANewLine(x);
1852
+
1853
+ for (let i = 0; i < x; i++) doSomethingWith(i);
1854
+ ```
1855
+
1856
+ **Exception:** `if` statements fitting on one line *may* elide the block.
1857
+
1858
+ ```
1859
+ if (x) x.doFoo();
1860
+ ```
1861
+
1862
+ ##### Assignment in control statements
1863
+
1864
+ Prefer to avoid assignment of variables inside control statements. Assignment
1865
+ can be easily mistaken for equality checks inside control statements.
1866
+
1867
+ ```
1868
+ if (x = someFunction()) {
1869
+ // Assignment easily mistaken with equality check
1870
+ // ...
1871
+ }
1872
+ ```
1873
+
1874
+ ```
1875
+ x = someFunction();
1876
+ if (x) {
1877
+ // ...
1878
+ }
1879
+ ```
1880
+
1881
+ In cases where assignment inside the control statement is preferred, enclose the
1882
+ assignment in additional parenthesis to indicate it is intentional.
1883
+
1884
+ ```
1885
+ while ((x = someFunction())) {
1886
+ // Double parenthesis shows assignment is intentional
1887
+ // ...
1888
+ }
1889
+ ```
1890
+
1891
+ ##### Iterating containers
1892
+
1893
+ Prefer `for (... of someArr)` to iterate over arrays. `Array.prototype.forEach` and vanilla `for`
1894
+ loops are also allowed:
1895
+
1896
+ ```
1897
+ for (const x of someArr) {
1898
+ // x is a value of someArr.
1899
+ }
1900
+
1901
+ for (let i = 0; i < someArr.length; i++) {
1902
+ // Explicitly count if the index is needed, otherwise use the for/of form.
1903
+ const x = someArr[i];
1904
+ // ...
1905
+ }
1906
+ for (const [i, x] of someArr.entries()) {
1907
+ // Alternative version of the above.
1908
+ }
1909
+ ```
1910
+
1911
+ `for`-`in` loops may only be used on dict-style objects (see
1912
+ [below](#optimization-compatibility-for-property-access) for more info). Do not
1913
+ use `for (... in ...)` to iterate over arrays as it will counterintuitively give
1914
+ the array's indices (as strings!), not values:
1915
+
1916
+ ```
1917
+ for (const x in someArray) {
1918
+ // x is the index!
1919
+ }
1920
+ ```
1921
+
1922
+ `Object.prototype.hasOwnProperty` should be used in `for`-`in` loops to exclude
1923
+ unwanted prototype properties. Prefer `for`-`of` with `Object.keys`,
1924
+ `Object.values`, or `Object.entries` over `for`-`in` when possible.
1925
+
1926
+ ```
1927
+ for (const key in obj) {
1928
+ if (!obj.hasOwnProperty(key)) continue;
1929
+ doWork(key, obj[key]);
1930
+ }
1931
+ for (const key of Object.keys(obj)) {
1932
+ doWork(key, obj[key]);
1933
+ }
1934
+ for (const value of Object.values(obj)) {
1935
+ doWorkValOnly(value);
1936
+ }
1937
+ for (const [key, value] of Object.entries(obj)) {
1938
+ doWork(key, value);
1939
+ }
1940
+ ```
1941
+
1942
+ #### Grouping parentheses
1943
+
1944
+ Optional grouping parentheses are omitted only when the author and reviewer
1945
+ agree that there is no reasonable chance that the code will be misinterpreted
1946
+ without them, nor would they have made the code easier to read. It is *not*
1947
+ reasonable to assume that every reader has the entire operator precedence table
1948
+ memorized.
1949
+
1950
+ Do not use unnecessary parentheses around the entire expression following
1951
+ `delete`, `typeof`, `void`, `return`, `throw`, `case`, `in`, `of`, or `yield`.
1952
+
1953
+ #### Exception handling
1954
+
1955
+ Exceptions are an important part of the language and should be used whenever
1956
+ exceptional cases occur.
1957
+
1958
+ Custom exceptions provide a great way to convey additional error information
1959
+ from functions. They should be defined and used wherever the native `Error` type
1960
+ is insufficient.
1961
+
1962
+ Prefer throwing exceptions over ad-hoc error-handling approaches (such as
1963
+ passing an error container reference type, or returning an object with an error
1964
+ property).
1965
+
1966
+ ##### Instantiate errors using `new`
1967
+
1968
+ Always use `new Error()` when instantiating exceptions, instead of just calling
1969
+ `Error()`. Both forms create a new `Error` instance, but using `new` is more
1970
+ consistent with how other objects are instantiated.
1971
+
1972
+ ```
1973
+ throw new Error('Foo is not a valid bar.');
1974
+ ```
1975
+
1976
+ ```
1977
+ throw Error('Foo is not a valid bar.');
1978
+ ```
1979
+
1980
+ ##### Only throw errors
1981
+
1982
+ JavaScript (and thus TypeScript) allow throwing or rejecting a Promise with
1983
+ arbitrary values. However if the thrown or rejected value is not an `Error`, it
1984
+ does not populate stack trace information, making debugging hard. This treatment
1985
+ extends to `Promise` rejection values as `Promise.reject(obj)` is equivalent to
1986
+ `throw obj;` in async functions.
1987
+
1988
+ ```
1989
+ // bad: does not get a stack trace.
1990
+ throw 'oh noes!';
1991
+ // For promises
1992
+ new Promise((resolve, reject) => void reject('oh noes!'));
1993
+ Promise.reject();
1994
+ Promise.reject('oh noes!');
1995
+ ```
1996
+
1997
+ Instead, only throw (subclasses of) `Error`:
1998
+
1999
+ ```
2000
+ // Throw only Errors
2001
+ throw new Error('oh noes!');
2002
+ // ... or subtypes of Error.
2003
+ class MyError extends Error {}
2004
+ throw new MyError('my oh noes!');
2005
+ // For promises
2006
+ new Promise((resolve) => resolve()); // No reject is OK.
2007
+ new Promise((resolve, reject) => void reject(new Error('oh noes!')));
2008
+ Promise.reject(new Error('oh noes!'));
2009
+ ```
2010
+
2011
+ ##### Catching and rethrowing
2012
+
2013
+ When catching errors, code *should* assume that all thrown errors are instances
2014
+ of `Error`.
2015
+
2016
+ ```
2017
+ function assertIsError(e: unknown): asserts e is Error {
2018
+ if (!(e instanceof Error)) throw new Error("e is not an Error");
2019
+ }
2020
+
2021
+ try {
2022
+ doSomething();
2023
+ } catch (e: unknown) {
2024
+ // All thrown errors must be Error subtypes. Do not handle
2025
+ // other possible values unless you know they are thrown.
2026
+ assertIsError(e);
2027
+ displayError(e.message);
2028
+ // or rethrow:
2029
+ throw e;
2030
+ }
2031
+ ```
2032
+
2033
+ Exception handlers *must not* defensively handle non-`Error` types unless the
2034
+ called API is conclusively known to throw non-`Error`s in violation of the above
2035
+ rule. In that case, a comment should be included to specifically identify where
2036
+ the non-`Error`s originate.
2037
+
2038
+ ```
2039
+ try {
2040
+ badApiThrowingStrings();
2041
+ } catch (e: unknown) {
2042
+ // Note: bad API throws strings instead of errors.
2043
+ if (typeof e === 'string') { ... }
2044
+ }
2045
+ ```
2046
+
2047
+ Why?
2048
+
2049
+ Avoid
2050
+ [overly defensive programming](https://en.wikipedia.org/wiki/Defensive_programming#Offensive_programming).
2051
+ Repeating the same defenses against a problem that will not exist in most code
2052
+ leads to boiler-plate code that is not useful.
2053
+
2054
+ ##### Empty catch blocks
2055
+
2056
+ It is very rarely correct to do nothing in response to a caught exception. When
2057
+ it truly is appropriate to take no action whatsoever in a catch block, the
2058
+ reason this is justified is explained in a comment.
2059
+
2060
+ ```
2061
+ try {
2062
+ return handleNumericResponse(response);
2063
+ } catch (e: unknown) {
2064
+ // Response is not numeric. Continue to handle as text.
2065
+ }
2066
+ return handleTextResponse(response);
2067
+ ```
2068
+
2069
+ Disallowed:
2070
+
2071
+ ```
2072
+ try {
2073
+ shouldFail();
2074
+ fail('expected an error');
2075
+ } catch (expected: unknown) {
2076
+ }
2077
+ ```
2078
+
2079
+ Tip: Unlike in some other languages, patterns like the above simply don’t work
2080
+ since this will catch the error thrown by `fail`. Use `assertThrows()` instead.
2081
+
2082
+ #### Switch statements
2083
+
2084
+ All `switch` statements *must* contain a `default` statement group, even if it
2085
+ contains no code. The `default` statement group must be last.
2086
+
2087
+ ```
2088
+ switch (x) {
2089
+ case Y:
2090
+ doSomethingElse();
2091
+ break;
2092
+ default:
2093
+ // nothing to do.
2094
+ }
2095
+ ```
2096
+
2097
+ Within a switch block, each statement group either terminates abruptly with a
2098
+ `break`, a `return` statement, or by throwing an exception. Non-empty statement
2099
+ groups (`case ...`) *must not* fall through (enforced by the compiler):
2100
+
2101
+ ```
2102
+ switch (x) {
2103
+ case X:
2104
+ doSomething();
2105
+ // fall through - not allowed!
2106
+ case Y:
2107
+ // ...
2108
+ }
2109
+ ```
2110
+
2111
+ Empty statement groups are allowed to fall through:
2112
+
2113
+ ```
2114
+ switch (x) {
2115
+ case X:
2116
+ case Y:
2117
+ doSomething();
2118
+ break;
2119
+ default: // nothing to do.
2120
+ }
2121
+ ```
2122
+
2123
+ #### Equality checks
2124
+
2125
+ Always use triple equals (`===`) and not equals (`!==`). The double equality
2126
+ operators cause error prone type coercions that are hard to understand and
2127
+ slower to implement for JavaScript Virtual Machines. See also the
2128
+ [JavaScript equality table](https://dorey.github.io/JavaScript-Equality-Table/).
2129
+
2130
+ ```
2131
+ if (foo == 'bar' || baz != bam) {
2132
+ // Hard to understand behaviour due to type coercion.
2133
+ }
2134
+ ```
2135
+
2136
+ ```
2137
+ if (foo === 'bar' || baz !== bam) {
2138
+ // All good here.
2139
+ }
2140
+ ```
2141
+
2142
+ **Exception:** Comparisons to the literal `null` value *may* use the `==` and
2143
+ `!=` operators to cover both `null` and `undefined` values.
2144
+
2145
+ ```
2146
+ if (foo == null) {
2147
+ // Will trigger when foo is null or undefined.
2148
+ }
2149
+ ```
2150
+
2151
+ #### Type and non-nullability assertions
2152
+
2153
+ Type assertions (`x as SomeType`) and non-nullability assertions (`y!`) are
2154
+ unsafe. Both only silence the TypeScript compiler, but do not insert any runtime
2155
+ checks to match these assertions, so they can cause your program to crash at
2156
+ runtime.
2157
+
2158
+ Because of this, you *should not* use type and non-nullability assertions
2159
+ without an obvious or explicit reason for doing so.
2160
+
2161
+ Instead of the following:
2162
+
2163
+ ```
2164
+ (x as Foo).foo();
2165
+
2166
+ y!.bar();
2167
+ ```
2168
+
2169
+ When you want to assert a type or non-nullability the best answer is to
2170
+ explicitly write a runtime check that performs that check.
2171
+
2172
+ ```
2173
+ // assuming Foo is a class.
2174
+ if (x instanceof Foo) {
2175
+ x.foo();
2176
+ }
2177
+
2178
+ if (y) {
2179
+ y.bar();
2180
+ }
2181
+ ```
2182
+
2183
+ Sometimes due to some local property of your code you can be sure that the
2184
+ assertion form is safe. In those situations, you *should* add clarification to
2185
+ explain why you are ok with the unsafe behavior:
2186
+
2187
+ ```
2188
+ // x is a Foo, because ...
2189
+ (x as Foo).foo();
2190
+
2191
+ // y cannot be null, because ...
2192
+ y!.bar();
2193
+ ```
2194
+
2195
+ If the reasoning behind a type or non-nullability assertion is obvious, the
2196
+ comments *may* not be necessary. For example, generated proto code is always
2197
+ nullable, but perhaps it is well-known in the context of the code that certain
2198
+ fields are always provided by the backend. Use your judgement.
2199
+
2200
+ ##### Type assertion syntax
2201
+
2202
+ Type assertions *must* use the `as` syntax (as opposed to the angle brackets
2203
+ syntax). This enforces parentheses around the assertion when accessing a member.
2204
+
2205
+ ```
2206
+ const x = (<Foo>z).length;
2207
+ const y = <Foo>z.length;
2208
+ ```
2209
+
2210
+ ```
2211
+ // z must be Foo because ...
2212
+ const x = (z as Foo).length;
2213
+ ```
2214
+
2215
+ ##### Double assertions
2216
+
2217
+ From the
2218
+ [TypeScript handbook](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-assertions),
2219
+ TypeScript only allows type assertions which convert to a *more specific* or
2220
+ *less specific* version of a type. Adding a type assertion (`x as Foo`) which
2221
+ does not meet this criteria will give the error: "Conversion of type 'X' to type
2222
+ 'Y' may be a mistake because neither type sufficiently overlaps with the other."
2223
+
2224
+ If you are sure an assertion is safe, you can perform a *double assertion*. This
2225
+ involves casting through `unknown` since it is less specific than all types.
2226
+
2227
+ ```
2228
+ // x is a Foo here, because...
2229
+ (x as unknown as Foo).fooMethod();
2230
+ ```
2231
+
2232
+ Use `unknown` (instead of `any` or `{}`) as the intermediate type.
2233
+
2234
+ ##### Type assertions and object literals
2235
+
2236
+ Use type annotations (`: Foo`) instead of type assertions (`as Foo`) to specify
2237
+ the type of an object literal. This allows detecting refactoring bugs when the
2238
+ fields of an interface change over time.
2239
+
2240
+ ```
2241
+ interface Foo {
2242
+ bar: number;
2243
+ baz?: string; // was "bam", but later renamed to "baz".
2244
+ }
2245
+
2246
+ const foo = {
2247
+ bar: 123,
2248
+ bam: 'abc', // no error!
2249
+ } as Foo;
2250
+
2251
+ function func() {
2252
+ return {
2253
+ bar: 123,
2254
+ bam: 'abc', // no error!
2255
+ } as Foo;
2256
+ }
2257
+ ```
2258
+
2259
+ ```
2260
+ interface Foo {
2261
+ bar: number;
2262
+ baz?: string;
2263
+ }
2264
+
2265
+ const foo: Foo = {
2266
+ bar: 123,
2267
+ bam: 'abc', // complains about "bam" not being defined on Foo.
2268
+ };
2269
+
2270
+ function func(): Foo {
2271
+ return {
2272
+ bar: 123,
2273
+ bam: 'abc', // complains about "bam" not being defined on Foo.
2274
+ };
2275
+ }
2276
+ ```
2277
+
2278
+ #### Keep try blocks focused
2279
+
2280
+ Limit the amount of code inside a try block, if this can be done without hurting
2281
+ readability.
2282
+
2283
+ ```
2284
+ try {
2285
+ const result = methodThatMayThrow();
2286
+ use(result);
2287
+ } catch (error: unknown) {
2288
+ // ...
2289
+ }
2290
+ ```
2291
+
2292
+ ```
2293
+ let result;
2294
+ try {
2295
+ result = methodThatMayThrow();
2296
+ } catch (error: unknown) {
2297
+ // ...
2298
+ }
2299
+ use(result);
2300
+ ```
2301
+
2302
+ Moving the non-throwable lines out of the try/catch block helps the reader learn
2303
+ which method throws exceptions. Some inline calls that do not throw exceptions
2304
+ could stay inside because they might not be worth the extra complication of a
2305
+ temporary variable.
2306
+
2307
+ **Exception:** There may be performance issues if try blocks are inside a loop.
2308
+ Widening try blocks to cover a whole loop is ok.
2309
+
2310
+ ### Decorators
2311
+
2312
+ Decorators are syntax with an `@` prefix, like `@MyDecorator`.
2313
+
2314
+ Do not define new decorators. Only use the decorators defined by
2315
+ frameworks:
2316
+
2317
+ * Angular (e.g. `@Component`, `@NgModule`, etc.)
2318
+ * Polymer (e.g. `@property`)
2319
+
2320
+ Why?
2321
+
2322
+ We generally want to avoid decorators, because they were an experimental feature
2323
+ that have since diverged from the TC39 proposal and have known bugs that won't
2324
+ be fixed.
2325
+
2326
+ When using decorators, the decorator *must* immediately precede the symbol it
2327
+ decorates, with no empty lines between:
2328
+
2329
+ ```
2330
+ /** JSDoc comments go before decorators */
2331
+ @Component({...}) // Note: no empty line after the decorator.
2332
+ class MyComp {
2333
+ @Input() myField: string; // Decorators on fields may be on the same line...
2334
+
2335
+ @Input()
2336
+ myOtherField: string; // ... or wrap.
2337
+ }
2338
+ ```
2339
+
2340
+ ### Disallowed features
2341
+
2342
+ #### Wrapper objects for primitive types
2343
+
2344
+ TypeScript code *must not* instantiate the wrapper classes for the primitive
2345
+ types `String`, `Boolean`, and `Number`. Wrapper classes have surprising
2346
+ behavior, such as `new Boolean(false)` evaluating to `true`.
2347
+
2348
+ ```
2349
+ const s = new String('hello');
2350
+ const b = new Boolean(false);
2351
+ const n = new Number(5);
2352
+ ```
2353
+
2354
+ The wrappers may be called as functions for coercing (which is preferred over
2355
+ using `+` or concatenating the empty string) or creating symbols. See
2356
+ [type coercion](#type-coercion) for more information.
2357
+
2358
+ #### Automatic Semicolon Insertion
2359
+
2360
+ Do not rely on Automatic Semicolon Insertion (ASI). Explicitly end all
2361
+ statements using a semicolon. This prevents bugs due to incorrect semicolon
2362
+ insertions and ensures compatibility with tools with limited ASI support (e.g.
2363
+ clang-format).
2364
+
2365
+ #### Const enums
2366
+
2367
+ Code *must not* use `const enum`; use plain `enum` instead.
2368
+
2369
+ Why?
2370
+
2371
+ TypeScript enums already cannot be mutated; `const enum` is a separate language
2372
+ feature related to optimization that makes the enum invisible to
2373
+ JavaScript users of the module.
2374
+
2375
+ #### Debugger statements
2376
+
2377
+ Debugger statements *must not* be included in production code.
2378
+
2379
+ ```
2380
+ function debugMe() {
2381
+ debugger;
2382
+ }
2383
+ ```
2384
+
2385
+ #### `with`
2386
+
2387
+ Do not use the `with` keyword. It makes your code harder to understand and
2388
+ [has been banned in strict mode since ES5](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with).
2389
+
2390
+ #### Dynamic code evaluation
2391
+
2392
+ Do not use `eval` or the `Function(...string)` constructor (except for code
2393
+ loaders). These features are potentially dangerous and simply do not work in
2394
+ environments using strict
2395
+ [Content Security Policies](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP).
2396
+
2397
+ #### Non-standard features
2398
+
2399
+ Do not use non-standard ECMAScript or Web Platform features.
2400
+
2401
+ This includes:
2402
+
2403
+ * Old features that have been marked deprecated or removed entirely from
2404
+ ECMAScript / the Web Platform (see
2405
+ [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Deprecated_and_obsolete_features))
2406
+ * New ECMAScript features that are not yet standardized
2407
+ + Avoid using features that are in current TC39 working draft or currently
2408
+ in the [proposal process](https://tc39.es/process-document/)
2409
+ + Use only ECMAScript features defined in the current ECMA-262
2410
+ specification
2411
+ * Proposed but not-yet-complete web standards:
2412
+ + WHATWG proposals that have not completed the
2413
+ [proposal process](https://whatwg.org/faq#adding-new-features).
2414
+ * Non-standard language “extensions” (such as those provided by some external
2415
+ transpilers)
2416
+
2417
+ Projects targeting specific JavaScript runtimes, such as latest-Chrome-only,
2418
+ Chrome extensions, Node.JS, Electron, can obviously use those APIs. Use caution
2419
+ when considering an API surface that is proprietary and only implemented in some
2420
+ browsers; consider whether there is a common library that can abstract this API
2421
+ surface away for you.
2422
+
2423
+ #### Modifying builtin objects
2424
+
2425
+ Never modify builtin types, either by adding methods to their constructors or to
2426
+ their prototypes. Avoid depending on libraries that do
2427
+ this.
2428
+
2429
+ Do not add symbols to the global object unless absolutely necessary (e.g.
2430
+ required by a third-party API).
2431
+
2432
+ ## Naming
2433
+
2434
+ ### Identifiers
2435
+
2436
+ Identifiers *must* use only ASCII letters, digits, underscores (for constants
2437
+ and structured test method names), and (rarely) the '$' sign.
2438
+
2439
+ #### Naming style
2440
+
2441
+ TypeScript expresses information in types, so names *should not* be decorated
2442
+ with information that is included in the type. (See also
2443
+ [Testing Blog](https://testing.googleblog.com/2017/10/code-health-identifiernamingpostforworl.html)
2444
+ for more about what
2445
+ not to include.)
2446
+
2447
+ Some concrete examples of this rule:
2448
+
2449
+ * Do not use trailing or leading underscores for private properties or
2450
+ methods.
2451
+ * Do not use the `opt_` prefix for optional parameters.
2452
+ + For accessors, see [accessor rules](#getters-and-setters-accessors)
2453
+ below.
2454
+ * Do not mark interfaces specially (~~`IMyInterface`~~ or
2455
+ ~~`MyFooInterface`~~) unless it's idiomatic in its
2456
+ environment. When
2457
+ introducing an interface for a class, give it a name that expresses why the
2458
+ interface exists in the first place (e.g. `class TodoItem` and `interface
2459
+ TodoItemStorage` if the interface expresses the format used for
2460
+ storage/serialization in JSON).
2461
+ * Suffixing `Observable`s with `$` is a common external convention and can
2462
+ help resolve confusion regarding observable values vs concrete values.
2463
+ Judgement on whether this is a useful convention is left up to individual
2464
+ teams, but *should* be consistent within projects.
2465
+
2466
+ #### Descriptive names
2467
+
2468
+ Names *must* be descriptive and clear to a new reader. Do not use abbreviations
2469
+ that are ambiguous or unfamiliar to readers outside your project, and do not
2470
+ abbreviate by deleting letters within a word.
2471
+
2472
+ * **Exception:** Variables that are in scope for 10 lines or fewer, including
2473
+ arguments that are *not* part of an exported API, *may* use short (e.g.
2474
+ single letter) variable names.
2475
+
2476
+ ```
2477
+ // Good identifiers:
2478
+ errorCount // No abbreviation.
2479
+ dnsConnectionIndex // Most people know what "DNS" stands for.
2480
+ referrerUrl // Ditto for "URL".
2481
+ customerId // "Id" is both ubiquitous and unlikely to be misunderstood.
2482
+ ```
2483
+
2484
+ ```
2485
+ // Disallowed identifiers:
2486
+ n // Meaningless.
2487
+ nErr // Ambiguous abbreviation.
2488
+ nCompConns // Ambiguous abbreviation.
2489
+ wgcConnections // Only your group knows what this stands for.
2490
+ pcReader // Lots of things can be abbreviated "pc".
2491
+ cstmrId // Deletes internal letters.
2492
+ kSecondsPerDay // Do not use Hungarian notation.
2493
+ customerID // Incorrect camelcase of "ID".
2494
+ ```
2495
+
2496
+ #### Camel case
2497
+
2498
+ Treat abbreviations like acronyms in names as whole words, i.e. use
2499
+ `loadHttpUrl`, not ~~`loadHTTPURL`~~, unless required by a platform name (e.g.
2500
+ `XMLHttpRequest`).
2501
+
2502
+ #### Dollar sign
2503
+
2504
+ Identifiers *should not* generally use `$`, except when required by naming
2505
+ conventions for third party frameworks. [See above](#naming-style) for more on
2506
+ using `$` with `Observable` values.
2507
+
2508
+ ### Rules by identifier type
2509
+
2510
+ Most identifier names should follow the casing in the table below, based on the
2511
+ identifier's type.
2512
+
2513
+ | Style | Category |
2514
+ | --- | --- |
2515
+ | `UpperCamelCase` | class / interface / type / enum / decorator / type parameters / component functions in TSX / JSXElement type parameter |
2516
+ | `lowerCamelCase` | variable / parameter / function / method / property / module alias |
2517
+ | `CONSTANT_CASE` | global constant values, including enum values. See [Constants](#identifiers-constants) below. |
2518
+ | `#ident` | private identifiers are never used. |
2519
+
2520
+ #### Type parameters
2521
+
2522
+ Type parameters, like in `Array<T>`, *may* use a single upper case character
2523
+ (`T`) or `UpperCamelCase`.
2524
+
2525
+ #### Test names
2526
+
2527
+ Test method names inxUnit-style test frameworks *may* be structured with `_` separators, e.g.
2528
+ `testX_whenY_doesZ()`.
2529
+
2530
+ #### `_` prefix/suffix
2531
+
2532
+ Identifiers must not use `_` as a prefix or suffix.
2533
+
2534
+ This also means that `_` *must not* be used as an identifier by itself (e.g. to
2535
+ indicate a parameter is unused).
2536
+
2537
+ > Tip: If you only need some of the elements from an array (or TypeScript
2538
+ > tuple), you can insert extra commas in a destructuring statement to ignore
2539
+ > in-between elements:
2540
+ >
2541
+ > ```
2542
+ > const [a, , b] = [1, 5, 10]; // a <- 1, b <- 10
2543
+ > ```
2544
+
2545
+ #### Imports
2546
+
2547
+ Module namespace imports are `lowerCamelCase` while files are `snake_case`,
2548
+ which means that imports correctly will not match in casing style, such as
2549
+
2550
+ ```
2551
+ import * as fooBar from './foo_bar';
2552
+ ```
2553
+
2554
+ Some libraries might commonly use a namespace import prefix that violates this
2555
+ naming scheme, but overbearingly common open source use makes the violating
2556
+ style more readable. The only libraries that currently fall under this exception
2557
+ are:
2558
+
2559
+ * [jquery](https://jquery.com/), using the `$` prefix
2560
+ * [threejs](https://threejs.org/), using the `THREE` prefix
2561
+
2562
+ #### Constants
2563
+
2564
+ **Immutable**: `CONSTANT_CASE` indicates that a value is *intended* to not be
2565
+ changed, and *may* be used for values that can technically be modified (i.e.
2566
+ values that are not deeply frozen) to indicate to users that they must not be
2567
+ modified.
2568
+
2569
+ ```
2570
+ const UNIT_SUFFIXES = {
2571
+ 'milliseconds': 'ms',
2572
+ 'seconds': 's',
2573
+ };
2574
+ // Even though per the rules of JavaScript UNIT_SUFFIXES is
2575
+ // mutable, the uppercase shows users to not modify it.
2576
+ ```
2577
+
2578
+ A constant can also be a `static readonly` property of a class.
2579
+
2580
+ ```
2581
+ class Foo {
2582
+ private static readonly MY_SPECIAL_NUMBER = 5;
2583
+
2584
+ bar() {
2585
+ return 2 * Foo.MY_SPECIAL_NUMBER;
2586
+ }
2587
+ }
2588
+ ```
2589
+
2590
+ **Global**: Only symbols declared on the module level, static fields of module
2591
+ level classes, and values of module level enums, *may* use `CONST_CASE`. If a
2592
+ value can be instantiated more than once over the lifetime of the program (e.g.
2593
+ a local variable declared within a function, or a static field on a class nested
2594
+ in a function) then it *must* use `lowerCamelCase`.
2595
+
2596
+ If a value is an arrow function that implements an interface, then it *may* be
2597
+ declared `lowerCamelCase`.
2598
+
2599
+ #### Aliases
2600
+
2601
+ When creating a local-scope alias of an existing symbol, use the format of the
2602
+ existing identifier. The local alias *must* match the existing naming and format
2603
+ of the source. For variables use `const` for your local aliases, and for class
2604
+ fields use the `readonly` attribute.
2605
+
2606
+ > Note: If you're creating an alias just to expose it to a template in your
2607
+ > framework of choice, remember to also apply the proper
2608
+ > [access modifiers](#properties-used-outside-of-class-lexical-scope).
2609
+
2610
+ ```
2611
+ const {BrewStateEnum} = SomeType;
2612
+ const CAPACITY = 5;
2613
+
2614
+ class Teapot {
2615
+ readonly BrewStateEnum = BrewStateEnum;
2616
+ readonly CAPACITY = CAPACITY;
2617
+ }
2618
+ ```
2619
+
2620
+ ## Type system
2621
+
2622
+ ### Type inference
2623
+
2624
+ Code *may* rely on type inference as implemented by the TypeScript compiler for
2625
+ all type expressions (variables, fields, return types, etc).
2626
+
2627
+ ```
2628
+ const x = 15; // Type inferred.
2629
+ ```
2630
+
2631
+ Leave out type annotations for trivially inferred types: variables or parameters
2632
+ initialized to a `string`, `number`, `boolean`, `RegExp` literal or `new`
2633
+ expression.
2634
+
2635
+ ```
2636
+ const x: boolean = true; // Bad: 'boolean' here does not aid readability
2637
+ ```
2638
+
2639
+ ```
2640
+ // Bad: 'Set' is trivially inferred from the initialization
2641
+ const x: Set<string> = new Set();
2642
+ ```
2643
+
2644
+ Explicitly specifying types may be required to prevent generic type parameters
2645
+ from being inferred as `unknown`. For example, initializing generic types with
2646
+ no values (e.g. empty arrays, objects, `Map`s, or `Set`s).
2647
+
2648
+ ```
2649
+ const x = new Set<string>();
2650
+ ```
2651
+
2652
+ For more complex expressions, type annotations can help with readability of the
2653
+ program:
2654
+
2655
+ ```
2656
+ // Hard to reason about the type of 'value' without an annotation.
2657
+ const value = await rpc.getSomeValue().transform();
2658
+ ```
2659
+
2660
+ ```
2661
+ // Can tell the type of 'value' at a glance.
2662
+ const value: string[] = await rpc.getSomeValue().transform();
2663
+ ```
2664
+
2665
+ Whether an annotation is required is decided by the code reviewer.
2666
+
2667
+ #### Return types
2668
+
2669
+ Whether to include return type annotations for functions and methods is up to
2670
+ the code author. Reviewers *may* ask for annotations to clarify complex return
2671
+ types that are hard to understand. Projects *may* have a local policy to always
2672
+ require return types, but this is not a general TypeScript style requirement.
2673
+
2674
+ There are two benefits to explicitly typing out the implicit return values of
2675
+ functions and methods:
2676
+
2677
+ * More precise documentation to benefit readers of the code.
2678
+ * Surface potential type errors faster in the future if there are code changes
2679
+ that change the return type of the function.
2680
+
2681
+ ### Undefined and null
2682
+
2683
+ TypeScript supports `undefined` and `null` types. Nullable types can be
2684
+ constructed as a union type (`string|null`); similarly with `undefined`. There
2685
+ is no special syntax for unions of `undefined` and `null`.
2686
+
2687
+ TypeScript code can use either `undefined` or `null` to denote absence of a
2688
+ value, there is no general guidance to prefer one over the other. Many
2689
+ JavaScript APIs use `undefined` (e.g. `Map.get`), while many DOM and Google APIs
2690
+ use `null` (e.g. `Element.getAttribute`), so the appropriate absent value
2691
+ depends on the context.
2692
+
2693
+ #### Nullable/undefined type aliases
2694
+
2695
+ Type aliases *must not* include `|null` or `|undefined` in a union type.
2696
+ Nullable aliases typically indicate that null values are being passed around
2697
+ through too many layers of an application, and this clouds the source of the
2698
+ original issue that resulted in `null`. They also make it unclear when specific
2699
+ values on a class or interface might be absent.
2700
+
2701
+ Instead, code *must* only add `|null` or `|undefined` when the alias is actually
2702
+ used. Code *should* deal with null values close to where they arise, using the
2703
+ above techniques.
2704
+
2705
+ ```
2706
+ // Bad
2707
+ type CoffeeResponse = Latte|Americano|undefined;
2708
+
2709
+ class CoffeeService {
2710
+ getLatte(): CoffeeResponse { ... };
2711
+ }
2712
+ ```
2713
+
2714
+ ```
2715
+ // Better
2716
+ type CoffeeResponse = Latte|Americano;
2717
+
2718
+ class CoffeeService {
2719
+ getLatte(): CoffeeResponse|undefined { ... };
2720
+ }
2721
+ ```
2722
+
2723
+ #### Prefer optional over `|undefined`
2724
+
2725
+ In addition, TypeScript supports a special construct for optional parameters and
2726
+ fields, using `?`:
2727
+
2728
+ ```
2729
+ interface CoffeeOrder {
2730
+ sugarCubes: number;
2731
+ milk?: Whole|LowFat|HalfHalf;
2732
+ }
2733
+
2734
+ function pourCoffee(volume?: Milliliter) { ... }
2735
+ ```
2736
+
2737
+ Optional parameters implicitly include `|undefined` in their type. However, they
2738
+ are different in that they can be left out when constructing a value or calling
2739
+ a method. For example, `{sugarCubes: 1}` is a valid `CoffeeOrder` because `milk`
2740
+ is optional.
2741
+
2742
+ Use optional fields (on interfaces or classes) and parameters rather than a
2743
+ `|undefined` type.
2744
+
2745
+ For classes preferably avoid this pattern altogether and initialize as many
2746
+ fields as possible.
2747
+
2748
+ ```
2749
+ class MyClass {
2750
+ field = '';
2751
+ }
2752
+ ```
2753
+
2754
+ ### Use structural types
2755
+
2756
+ TypeScript's type system is structural, not nominal. That is, a value matches a
2757
+ type if it has at least all the properties the type requires and the properties'
2758
+ types match, recursively.
2759
+
2760
+ When providing a structural-based implementation, explicitly include the type at
2761
+ the declaration of the symbol (this allows more precise type checking and error
2762
+ reporting).
2763
+
2764
+ ```
2765
+ const foo: Foo = {
2766
+ a: 123,
2767
+ b: 'abc',
2768
+ }
2769
+ ```
2770
+
2771
+ ```
2772
+ const badFoo = {
2773
+ a: 123,
2774
+ b: 'abc',
2775
+ }
2776
+ ```
2777
+
2778
+ Use interfaces to define structural types, not classes
2779
+
2780
+ ```
2781
+ interface Foo {
2782
+ a: number;
2783
+ b: string;
2784
+ }
2785
+
2786
+ const foo: Foo = {
2787
+ a: 123,
2788
+ b: 'abc',
2789
+ }
2790
+ ```
2791
+
2792
+ ```
2793
+ class Foo {
2794
+ readonly a: number;
2795
+ readonly b: number;
2796
+ }
2797
+
2798
+ const foo: Foo = {
2799
+ a: 123,
2800
+ b: 'abc',
2801
+ }
2802
+ ```
2803
+
2804
+ Why?
2805
+
2806
+ The "badFoo" object above relies on type inference. Additional fields could be
2807
+ added to "badFoo" and the type is inferred based on the object itself.
2808
+
2809
+ When passing a "badFoo" to a function that takes a "Foo", the error will be at
2810
+ the function call site, rather than at the object declaration site. This is also
2811
+ useful when changing the surface of an interface across broad codebases.
2812
+
2813
+ ```
2814
+ interface Animal {
2815
+ sound: string;
2816
+ name: string;
2817
+ }
2818
+
2819
+ function makeSound(animal: Animal) {}
2820
+
2821
+ /**
2822
+ * 'cat' has an inferred type of '{sound: string}'
2823
+ */
2824
+ const cat = {
2825
+ sound: 'meow',
2826
+ };
2827
+
2828
+ /**
2829
+ * 'cat' does not meet the type contract required for the function, so the
2830
+ * TypeScript compiler errors here, which may be very far from where 'cat' is
2831
+ * defined.
2832
+ */
2833
+ makeSound(cat);
2834
+
2835
+ /**
2836
+ * Horse has a structural type and the type error shows here rather than the
2837
+ * function call. 'horse' does not meet the type contract of 'Animal'.
2838
+ */
2839
+ const horse: Animal = {
2840
+ sound: 'niegh',
2841
+ };
2842
+
2843
+ const dog: Animal = {
2844
+ sound: 'bark',
2845
+ name: 'MrPickles',
2846
+ };
2847
+
2848
+ makeSound(dog);
2849
+ makeSound(horse);
2850
+ ```
2851
+
2852
+ ### Prefer interfaces over type literal aliases
2853
+
2854
+ TypeScript supports
2855
+ [type aliases](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-aliases)
2856
+ for naming a type expression. This can be used to name primitives, unions,
2857
+ tuples, and any other types.
2858
+
2859
+ However, when declaring types for objects, use interfaces instead of a type
2860
+ alias for the object literal expression.
2861
+
2862
+ ```
2863
+ interface User {
2864
+ firstName: string;
2865
+ lastName: string;
2866
+ }
2867
+ ```
2868
+
2869
+ ```
2870
+ type User = {
2871
+ firstName: string,
2872
+ lastName: string,
2873
+ }
2874
+ ```
2875
+
2876
+ Why?
2877
+
2878
+ These forms are nearly equivalent, so under the principle of just choosing one
2879
+ out of two forms to prevent variation, we should choose one. Additionally, there
2880
+ are also
2881
+ [interesting technical reasons to prefer interface](https://ncjamieson.com/prefer-interfaces/).
2882
+ That page quotes the TypeScript team lead: "Honestly, my take is that it should
2883
+ really just be interfaces for anything that they can model. There is no benefit
2884
+ to type aliases when there are so many issues around display/perf."
2885
+
2886
+ ### `Array<T>` Type
2887
+
2888
+ For simple types (containing just alphanumeric characters and dot), use the
2889
+ syntax sugar for arrays, `T[]` or `readonly T[]`, rather than the longer form
2890
+ `Array<T>` or `ReadonlyArray<T>`.
2891
+
2892
+ For multi-dimensional non-`readonly` arrays of simple types, use the syntax
2893
+ sugar form (`T[][]`, `T[][][]`, and so on) rather than the longer form.
2894
+
2895
+ For anything more complex, use the longer form `Array<T>`.
2896
+
2897
+ These rules apply at each level of nesting, i.e. a simple `T[]` nested in a more
2898
+ complex type would still be spelled as `T[]`, using the syntax sugar.
2899
+
2900
+ ```
2901
+ let a: string[];
2902
+ let b: readonly string[];
2903
+ let c: ns.MyObj[];
2904
+ let d: string[][];
2905
+ let e: Array<{n: number, s: string}>;
2906
+ let f: Array<string|number>;
2907
+ let g: ReadonlyArray<string|number>;
2908
+ let h: InjectionToken<string[]>; // Use syntax sugar for nested types.
2909
+ let i: ReadonlyArray<string[]>;
2910
+ let j: Array<readonly string[]>;
2911
+ ```
2912
+
2913
+ ```
2914
+ let a: Array<string>; // The syntax sugar is shorter.
2915
+ let b: ReadonlyArray<string>;
2916
+ let c: Array<ns.MyObj>;
2917
+ let d: Array<string[]>;
2918
+ let e: {n: number, s: string}[]; // The braces make it harder to read.
2919
+ let f: (string|number)[]; // Likewise with parens.
2920
+ let g: readonly (string | number)[];
2921
+ let h: InjectionToken<Array<string>>;
2922
+ let i: readonly string[][];
2923
+ let j: (readonly string[])[];
2924
+ ```
2925
+
2926
+ ### Indexable types / index signatures (`{[key: string]: T}`)
2927
+
2928
+ In JavaScript, it's common to use an object as an associative array (aka "map",
2929
+ "hash", or "dict"). Such objects can be typed using an
2930
+ [index signature](https://www.typescriptlang.org/docs/handbook/2/objects.html#index-signatures)
2931
+ (`[k: string]: T`) in TypeScript:
2932
+
2933
+ ```
2934
+ const fileSizes: {[fileName: string]: number} = {};
2935
+ fileSizes['readme.txt'] = 541;
2936
+ ```
2937
+
2938
+ In TypeScript, provide a meaningful label for the key. (The label only exists
2939
+ for documentation; it's unused otherwise.)
2940
+
2941
+ ```
2942
+ const users: {[key: string]: number} = ...;
2943
+ ```
2944
+
2945
+ ```
2946
+ const users: {[userName: string]: number} = ...;
2947
+ ```
2948
+
2949
+ > Rather than using one of these, consider using the ES6 `Map` and `Set` types
2950
+ > instead. JavaScript objects have
2951
+ > [surprising undesirable behaviors](http://2ality.com/2012/01/objects-as-maps.html)
2952
+ > and the ES6 types more explicitly convey your intent. Also, `Map`s can be
2953
+ > keyed by—and `Set`s can contain—types other than `string`.
2954
+
2955
+ TypeScript's builtin `Record<Keys, ValueType>` type allows constructing types
2956
+ with a defined set of keys. This is distinct from associative arrays in that the
2957
+ keys are statically known. See advice on that
2958
+ [below](#mapped-conditional-types).
2959
+
2960
+ ### Mapped and conditional types
2961
+
2962
+ TypeScript's
2963
+ [mapped types](https://www.typescriptlang.org/docs/handbook/2/mapped-types.html)
2964
+ and
2965
+ [conditional types](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html)
2966
+ allow specifying new types based on other types. TypeScript's standard library
2967
+ includes several type operators based on these (`Record`, `Partial`, `Readonly`
2968
+ etc).
2969
+
2970
+ These type system features allow succinctly specifying types and constructing
2971
+ powerful yet type safe abstractions. They come with a number of drawbacks
2972
+ though:
2973
+
2974
+ * Compared to explicitly specifying properties and type relations (e.g. using
2975
+ interfaces and extension, see below for an example), type operators require
2976
+ the reader to mentally evaluate the type expression. This can make programs
2977
+ substantially harder to read, in particular combined with type inference and
2978
+ expressions crossing file boundaries.
2979
+ * Mapped & conditional types' evaluation model, in particular when combined
2980
+ with type inference, is underspecified, not always well understood, and
2981
+ often subject to change in TypeScript compiler versions. Code can
2982
+ "accidentally" compile or seem to give the right results. This increases
2983
+ future support cost of code using type operators.
2984
+ * Mapped & conditional types are most powerful when deriving types from
2985
+ complex and/or inferred types. On the flip side, this is also when they are
2986
+ most prone to create hard to understand and maintain programs.
2987
+ * Some language tooling does not work well with these type system features.
2988
+ E.g. your IDE's find references (and thus rename property refactoring) will
2989
+ not find properties in a `Pick<T, Keys>` type, and Code Search won't
2990
+ hyperlink them.
2991
+
2992
+ The style recommendation is:
2993
+
2994
+ * Always use the simplest type construct that can possibly express your code.
2995
+ * A little bit of repetition or verbosity is often much cheaper than the long
2996
+ term cost of complex type expressions.
2997
+ * Mapped & conditional types may be used, subject to these considerations.
2998
+
2999
+ For example, TypeScript's builtin `Pick<T, Keys>` type allows creating a new
3000
+ type by subsetting another type `T`, but simple interface extension can often be
3001
+ easier to understand.
3002
+
3003
+ ```
3004
+ interface User {
3005
+ shoeSize: number;
3006
+ favoriteIcecream: string;
3007
+ favoriteChocolate: string;
3008
+ }
3009
+
3010
+ // FoodPreferences has favoriteIcecream and favoriteChocolate, but not shoeSize.
3011
+ type FoodPreferences = Pick<User, 'favoriteIcecream'|'favoriteChocolate'>;
3012
+ ```
3013
+
3014
+ This is equivalent to spelling out the properties on `FoodPreferences`:
3015
+
3016
+ ```
3017
+ interface FoodPreferences {
3018
+ favoriteIcecream: string;
3019
+ favoriteChocolate: string;
3020
+ }
3021
+ ```
3022
+
3023
+ To reduce duplication, `User` could extend `FoodPreferences`, or (possibly
3024
+ better) nest a field for food preferences:
3025
+
3026
+ ```
3027
+ interface FoodPreferences { /* as above */ }
3028
+ interface User extends FoodPreferences {
3029
+ shoeSize: number;
3030
+ // also includes the preferences.
3031
+ }
3032
+ ```
3033
+
3034
+ Using interfaces here makes the grouping of properties explicit, improves IDE
3035
+ support, allows better optimization, and arguably makes the code easier to
3036
+ understand.
3037
+
3038
+ ### `any` Type
3039
+
3040
+ TypeScript's `any` type is a super and subtype of all other types, and allows
3041
+ dereferencing all properties. As such, `any` is dangerous - it can mask severe
3042
+ programming errors, and its use undermines the value of having static types in
3043
+ the first place.
3044
+
3045
+ **Consider *not* to use `any`.** In circumstances where you want to use `any`,
3046
+ consider one of:
3047
+
3048
+ * [Provide a more specific type](#any-specific)
3049
+ * [Use `unknown`](#any-unknown)
3050
+ * [Suppress the lint warning and document why](#any-suppress)
3051
+
3052
+ #### Providing a more specific type
3053
+
3054
+ Use interfaces , an
3055
+ inline object type, or a type alias:
3056
+
3057
+ ```
3058
+ // Use declared interfaces to represent server-side JSON.
3059
+ declare interface MyUserJson {
3060
+ name: string;
3061
+ email: string;
3062
+ }
3063
+
3064
+ // Use type aliases for types that are repetitive to write.
3065
+ type MyType = number|string;
3066
+
3067
+ // Or use inline object types for complex returns.
3068
+ function getTwoThings(): {something: number, other: string} {
3069
+ // ...
3070
+ return {something, other};
3071
+ }
3072
+
3073
+ // Use a generic type, where otherwise a library would say `any` to represent
3074
+ // they don't care what type the user is operating on (but note "Return type
3075
+ // only generics" below).
3076
+ function nicestElement<T>(items: T[]): T {
3077
+ // Find the nicest element in items.
3078
+ // Code can also put constraints on T, e.g. <T extends HTMLElement>.
3079
+ }
3080
+ ```
3081
+
3082
+ #### Using `unknown` over `any`
3083
+
3084
+ The `any` type allows assignment into any other type and dereferencing any
3085
+ property off it. Often this behaviour is not necessary or desirable, and code
3086
+ just needs to express that a type is unknown. Use the built-in type `unknown` in
3087
+ that situation — it expresses the concept and is much safer as it does not allow
3088
+ dereferencing arbitrary properties.
3089
+
3090
+ ```
3091
+ // Can assign any value (including null or undefined) into this but cannot
3092
+ // use it without narrowing the type or casting.
3093
+ const val: unknown = value;
3094
+ ```
3095
+
3096
+ ```
3097
+ const danger: any = value /* result of an arbitrary expression */;
3098
+ danger.whoops(); // This access is completely unchecked!
3099
+ ```
3100
+
3101
+ To safely use `unknown` values, narrow the type using a
3102
+ [type guard](https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-differentiating-types)
3103
+
3104
+ #### Suppressing `any` lint warnings
3105
+
3106
+ Sometimes using `any` is legitimate, for example in tests to construct a mock
3107
+ object. In such cases, add a comment that suppresses the lint warning, and
3108
+ document why it is legitimate.
3109
+
3110
+ ```
3111
+ // This test only needs a partial implementation of BookService, and if
3112
+ // we overlooked something the test will fail in an obvious way.
3113
+ // This is an intentionally unsafe partial mock
3114
+ // tslint:disable-next-line:no-any
3115
+ const mockBookService = ({get() { return mockBook; }} as any) as BookService;
3116
+ // Shopping cart is not used in this test
3117
+ // tslint:disable-next-line:no-any
3118
+ const component = new MyComponent(mockBookService, /* unused ShoppingCart */ null as any);
3119
+ ```
3120
+
3121
+ ### `{}` Type
3122
+
3123
+ The `{}` type, also known as an *empty interface* type, represents a interface
3124
+ with no properties. An empty interface type has no specified properties and
3125
+ therefore any non-nullish value is assignable to it.
3126
+
3127
+ ```
3128
+ let player: {};
3129
+
3130
+ player = {
3131
+ health: 50,
3132
+ }; // Allowed.
3133
+
3134
+ console.log(player.health) // Property 'health' does not exist on type '{}'.
3135
+ ```
3136
+
3137
+ ```
3138
+ function takeAnything(obj:{}) {
3139
+
3140
+ }
3141
+
3142
+ takeAnything({});
3143
+ takeAnything({ a: 1, b: 2 });
3144
+ ```
3145
+
3146
+ Google3 code **should not** use `{}` for most use cases. `{}` represents any
3147
+ non-nullish primitive or object type, which is rarely appropriate. Prefer one of
3148
+ the following more-descriptive types:
3149
+
3150
+ * `unknown` can hold any value, including `null` or `undefined`, and is
3151
+ generally more appropriate for opaque values.
3152
+ * `Record<string, T>` is better for dictionary-like objects, and provides
3153
+ better type safety by being explicit about the type `T` of contained values
3154
+ (which may itself be `unknown`).
3155
+ * `object` excludes primitives as well, leaving only non-nullish functions and
3156
+ objects, but without any other assumptions about what properties may be
3157
+ available.
3158
+
3159
+ ### Tuple types
3160
+
3161
+ If you are tempted to create a Pair type, instead use a tuple type:
3162
+
3163
+ ```
3164
+ interface Pair {
3165
+ first: string;
3166
+ second: string;
3167
+ }
3168
+ function splitInHalf(input: string): Pair {
3169
+ ...
3170
+ return {first: x, second: y};
3171
+ }
3172
+ ```
3173
+
3174
+ ```
3175
+ function splitInHalf(input: string): [string, string] {
3176
+ ...
3177
+ return [x, y];
3178
+ }
3179
+
3180
+ // Use it like:
3181
+ const [leftHalf, rightHalf] = splitInHalf('my string');
3182
+ ```
3183
+
3184
+ However, often it's clearer to provide meaningful names for the properties.
3185
+
3186
+ If declaring an `interface` is too heavyweight, you can use an inline object
3187
+ literal type:
3188
+
3189
+ ```
3190
+ function splitHostPort(address: string): {host: string, port: number} {
3191
+ ...
3192
+ }
3193
+
3194
+ // Use it like:
3195
+ const address = splitHostPort(userAddress);
3196
+ use(address.port);
3197
+
3198
+ // You can also get tuple-like behavior using destructuring:
3199
+ const {host, port} = splitHostPort(userAddress);
3200
+ ```
3201
+
3202
+ ### Wrapper types
3203
+
3204
+ There are a few types related to JavaScript primitives that *should not* ever be
3205
+ used:
3206
+
3207
+ * `String`, `Boolean`, and `Number` have slightly different meaning from the
3208
+ corresponding primitive types `string`, `boolean`, and `number`. Always use
3209
+ the lowercase version.
3210
+ * `Object` has similarities to both `{}` and `object`, but is slightly looser.
3211
+ Use `{}` for a type that include everything except `null` and `undefined`,
3212
+ or lowercase `object` to further exclude the other primitive types (the
3213
+ three mentioned above, plus `symbol` and `bigint`).
3214
+
3215
+ Further, never invoke the wrapper types as constructors (with `new`).
3216
+
3217
+ ### Return type only generics
3218
+
3219
+ Avoid creating APIs that have return type only generics. When working with
3220
+ existing APIs that have return type only generics always explicitly specify the
3221
+ generics.
3222
+
3223
+ ## Toolchain requirements
3224
+
3225
+ Google style requires using a number of tools in specific ways, outlined here.
3226
+
3227
+ ### TypeScript compiler
3228
+
3229
+ All TypeScript files must pass type checking using the standard
3230
+ tool chain.
3231
+
3232
+ #### @ts-ignore
3233
+
3234
+ Do not use `@ts-ignore` nor the variants `@ts-expect-error` or `@ts-nocheck`.
3235
+
3236
+ Why?
3237
+
3238
+ They superficially seem to be an easy way to "fix" a compiler error, but in
3239
+ practice, a specific compiler error is often caused by a larger problem that can
3240
+ be fixed more directly.
3241
+
3242
+ For example, if you are using `@ts-ignore` to suppress a type error, then it's
3243
+ hard to predict what types the surrounding code will end up seeing. For many
3244
+ type errors, the advice in [how to best use `any`](#any) is useful.
3245
+
3246
+ You may use `@ts-expect-error` in unit tests, though you generally *should not*.
3247
+ `@ts-expect-error` suppresses all errors. It's easy to accidentally over-match
3248
+ and suppress more serious errors. Consider one of:
3249
+
3250
+ * When testing APIs that need to deal with unchecked values at runtime, add
3251
+ casts to the expected type or to `any` and add an explanatory comment. This
3252
+ limits error suppression to a single expression.
3253
+ * Suppress the lint warning and document why, similar to
3254
+ [suppressing `any` lint warnings](#any-suppress).
3255
+
3256
+ ### Conformance
3257
+
3258
+ Google TypeScript includes several *conformance frameworks*,
3259
+ [tsetse](https://tsetse.info) and
3260
+ [tsec](https://github.com/google/tsec).
3261
+
3262
+ These rules are commonly used to enforce critical restrictions (such as defining
3263
+ globals, which could break the codebase) and security patterns (such as using
3264
+ `eval` or assigning to `innerHTML`), or more loosely to improve code quality.
3265
+
3266
+ Google-style TypeScript must abide by any applicable global or framework-local
3267
+ conformance rules.
3268
+
3269
+ ## Comments and documentation
3270
+
3271
+ #### JSDoc versus comments
3272
+
3273
+ There are two types of comments, JSDoc (`/** ... */`) and non-JSDoc ordinary
3274
+ comments (`// ...` or `/* ... */`).
3275
+
3276
+ * Use `/** JSDoc */` comments for documentation, i.e. comments a user of the
3277
+ code should read.
3278
+ * Use `// line comments` for implementation comments, i.e. comments that only
3279
+ concern the implementation of the code itself.
3280
+
3281
+ JSDoc comments are understood by tools (such as editors and documentation
3282
+ generators), while ordinary comments are only for other humans.
3283
+
3284
+ #### Multi-line comments
3285
+
3286
+ Multi-line comments are indented at the same level as the surrounding code. They
3287
+ *must* use multiple single-line comments (`//`-style), not block comment style
3288
+ (`/* */`).
3289
+
3290
+ ```
3291
+ // This is
3292
+ // fine
3293
+ ```
3294
+
3295
+ ```
3296
+ /*
3297
+ * This should
3298
+ * use multiple
3299
+ * single-line comments
3300
+ */
3301
+
3302
+ /* This should use // */
3303
+ ```
3304
+
3305
+ Comments are not enclosed in boxes drawn with asterisks or other characters.
3306
+
3307
+ ### JSDoc general form
3308
+
3309
+ The basic formatting of JSDoc comments is as seen in this example:
3310
+
3311
+ ```
3312
+ /**
3313
+ * Multiple lines of JSDoc text are written here,
3314
+ * wrapped normally.
3315
+ * @param arg A number to do something to.
3316
+ */
3317
+ function doSomething(arg: number) { … }
3318
+ ```
3319
+
3320
+ or in this single-line example:
3321
+
3322
+ ```
3323
+ /** This short jsdoc describes the function. */
3324
+ function doSomething(arg: number) { … }
3325
+ ```
3326
+
3327
+ If a single-line comment overflows into multiple lines, it *must* use the
3328
+ multi-line style with `/**` and `*/` on their own lines.
3329
+
3330
+ Many tools extract metadata from JSDoc comments to perform code validation and
3331
+ optimization. As such, these comments *must* be well-formed.
3332
+
3333
+ ### Markdown
3334
+
3335
+ JSDoc is written in Markdown, though it *may* include HTML when necessary.
3336
+
3337
+ This means that tooling parsing JSDoc will ignore plain text formatting, so if
3338
+ you did this:
3339
+
3340
+ ```
3341
+ /**
3342
+ * Computes weight based on three factors:
3343
+ * items sent
3344
+ * items received
3345
+ * last timestamp
3346
+ */
3347
+ ```
3348
+
3349
+ it will be rendered like this:
3350
+
3351
+ ```
3352
+ Computes weight based on three factors: items sent items received last timestamp
3353
+ ```
3354
+
3355
+ Instead, write a Markdown list:
3356
+
3357
+ ```
3358
+ /**
3359
+ * Computes weight based on three factors:
3360
+ *
3361
+ * - items sent
3362
+ * - items received
3363
+ * - last timestamp
3364
+ */
3365
+ ```
3366
+
3367
+ ### JSDoc tags
3368
+
3369
+ Google style allows a subset of JSDoc tags. Most tags must occupy their own line, with the tag at the beginning
3370
+ of the line.
3371
+
3372
+ ```
3373
+ /**
3374
+ * The "param" tag must occupy its own line and may not be combined.
3375
+ * @param left A description of the left param.
3376
+ * @param right A description of the right param.
3377
+ */
3378
+ function add(left: number, right: number) { ... }
3379
+ ```
3380
+
3381
+ ```
3382
+ /**
3383
+ * The "param" tag must occupy its own line and may not be combined.
3384
+ * @param left @param right
3385
+ */
3386
+ function add(left: number, right: number) { ... }
3387
+ ```
3388
+
3389
+ ### Line wrapping
3390
+
3391
+ Line-wrapped block tags are indented four spaces. Wrapped description text *may*
3392
+ be lined up with the description on previous lines, but this horizontal
3393
+ alignment is discouraged.
3394
+
3395
+ ```
3396
+ /**
3397
+ * Illustrates line wrapping for long param/return descriptions.
3398
+ * @param foo This is a param with a particularly long description that just
3399
+ * doesn't fit on one line.
3400
+ * @return This returns something that has a lengthy description too long to fit
3401
+ * in one line.
3402
+ */
3403
+ exports.method = function(foo) {
3404
+ return 5;
3405
+ };
3406
+ ```
3407
+
3408
+ Do not indent when wrapping a `@desc` or `@fileoverview` description.
3409
+
3410
+ ### Document all top-level exports of modules
3411
+
3412
+ Use `/** JSDoc */` comments to communicate information to the users of your
3413
+ code. Avoid merely restating the property or parameter name. You *should* also
3414
+ document all properties and methods (exported/public or not) whose purpose is
3415
+ not immediately obvious from their name, as judged by your reviewer.
3416
+
3417
+ **Exception:** Symbols that are only exported to be consumed by tooling, such as
3418
+ @NgModule classes, do not require comments.
3419
+
3420
+ ### Class comments
3421
+
3422
+ JSDoc comments for classes should provide the reader with enough information to
3423
+ know how and when to use the class, as well as any additional considerations
3424
+ necessary to correctly use the class. Textual descriptions may be omitted on the
3425
+ constructor.
3426
+
3427
+ ### Method and function comments
3428
+
3429
+ Method, parameter, and return descriptions may be omitted if they are obvious
3430
+ from the rest of the method’s JSDoc or from the method name and type signature.
3431
+
3432
+ Method descriptions begin with a verb phrase that describes what the method
3433
+ does. This phrase is not an imperative sentence, but instead is written in the
3434
+ third person, as if there is an implied "This method ..." before it.
3435
+
3436
+ ### Parameter property comments
3437
+
3438
+ A
3439
+ [parameter property](https://www.typescriptlang.org/docs/handbook/2/classes.html#parameter-properties)
3440
+ is a constructor parameter that is prefixed by one of the modifiers `private`,
3441
+ `protected`, `public`, or `readonly`. A parameter property declares both a
3442
+ parameter and an instance property, and implicitly assigns into it. For example,
3443
+ `constructor(private readonly foo: Foo)`, declares that the constructor takes a
3444
+ parameter `foo`, but also declares a private readonly property `foo`, and
3445
+ assigns the parameter into that property before executing the remainder of the
3446
+ constructor.
3447
+
3448
+ To document these fields, use JSDoc's `@param` annotation. Editors display the
3449
+ description on constructor calls and property accesses.
3450
+
3451
+ ```
3452
+ /** This class demonstrates how parameter properties are documented. */
3453
+ class ParamProps {
3454
+ /**
3455
+ * @param percolator The percolator used for brewing.
3456
+ * @param beans The beans to brew.
3457
+ */
3458
+ constructor(
3459
+ private readonly percolator: Percolator,
3460
+ private readonly beans: CoffeeBean[]) {}
3461
+ }
3462
+ ```
3463
+
3464
+ ```
3465
+ /** This class demonstrates how ordinary fields are documented. */
3466
+ class OrdinaryClass {
3467
+ /** The bean that will be used in the next call to brew(). */
3468
+ nextBean: CoffeeBean;
3469
+
3470
+ constructor(initialBean: CoffeeBean) {
3471
+ this.nextBean = initialBean;
3472
+ }
3473
+ }
3474
+ ```
3475
+
3476
+ ### JSDoc type annotations
3477
+
3478
+ JSDoc type annotations are redundant in TypeScript source code. Do not declare
3479
+ types in `@param` or `@return` blocks, do not write `@implements`, `@enum`,
3480
+ `@private`, `@override` etc. on code that uses the `implements`, `enum`,
3481
+ `private`, `override` etc. keywords.
3482
+
3483
+ ### Make comments that actually add information
3484
+
3485
+ For non-exported symbols, sometimes the name and type of the function or
3486
+ parameter is enough. Code will *usually* benefit from more documentation than
3487
+ just variable names though!
3488
+
3489
+ * Avoid comments that just restate the parameter name and type, e.g.
3490
+
3491
+ ```
3492
+ /** @param fooBarService The Bar service for the Foo application. */
3493
+ ```
3494
+ * Because of this rule, `@param` and `@return` lines are only required when
3495
+ they add information, and *may* otherwise be omitted.
3496
+
3497
+ ```
3498
+ /**
3499
+ * POSTs the request to start coffee brewing.
3500
+ * @param amountLitres The amount to brew. Must fit the pot size!
3501
+ */
3502
+ brew(amountLitres: number, logger: Logger) {
3503
+ // ...
3504
+ }
3505
+ ```
3506
+
3507
+ #### Comments when calling a function
3508
+
3509
+ “Parameter name” comments should be used whenever the method name and parameter
3510
+ value do not sufficiently convey the meaning of the parameter.
3511
+
3512
+ Before adding these comments, consider refactoring the method to instead accept
3513
+ an interface and destructure it to greatly improve call-site
3514
+ readability.
3515
+
3516
+ "Parameter name" comments go before the parameter value, and include the
3517
+ parameter name and a `=` suffix:
3518
+
3519
+ ```
3520
+ someFunction(obviousParam, /* shouldRender= */ true, /* name= */ 'hello');
3521
+ ```
3522
+
3523
+ Existing code may use a legacy parameter name comment style, which places these
3524
+ comments ~after~ the parameter value and omits the `=`. Continuing to use this
3525
+ style within the file for consistency is acceptable.
3526
+
3527
+ ```
3528
+ someFunction(obviousParam, true /* shouldRender */, 'hello' /* name */);
3529
+ ```
3530
+
3531
+ ### Place documentation prior to decorators
3532
+
3533
+ When a class, method, or property have both decorators like `@Component` and
3534
+ JsDoc, please make sure to write the JsDoc before the decorator.
3535
+
3536
+ * Do not write JsDoc between the Decorator and the decorated statement.
3537
+
3538
+ ```
3539
+ @Component({
3540
+ selector: 'foo',
3541
+ template: 'bar',
3542
+ })
3543
+ /** Component that prints "bar". */
3544
+ export class FooComponent {}
3545
+ ```
3546
+ * Write the JsDoc block before the Decorator.
3547
+
3548
+ ```
3549
+ /** Component that prints "bar". */
3550
+ @Component({
3551
+ selector: 'foo',
3552
+ template: 'bar',
3553
+ })
3554
+ export class FooComponent {}
3555
+ ```
3556
+
3557
+ ## Policies
3558
+
3559
+ ### Consistency
3560
+
3561
+ For any style question that isn't settled definitively by this specification, do
3562
+ what the other code in the same file is already doing ("be consistent"). If that
3563
+ doesn't resolve the question, consider emulating the other files in the same
3564
+ directory.
3565
+
3566
+ Brand new files *must* use Google Style, regardless of the style choices of
3567
+ other files in the same package. When adding new code to a file that is not in
3568
+ Google Style, reformatting the existing code first is recommended, subject to
3569
+ the advice [below](#reformatting-existing-code). If this reformatting is not
3570
+ done, then new code *should* be as consistent as possible with existing code in
3571
+ the same file, but *must not* violate the style guide.
3572
+
3573
+ #### Reformatting existing code
3574
+
3575
+ You will occasionally encounter files in the codebase that are not in proper
3576
+ Google Style. These may have come from an acquisition, or may have been written
3577
+ before Google Style took a position on some issue, or may be in non-Google Style
3578
+ for any other reason.
3579
+
3580
+ When updating the style of existing code, follow these guidelines.
3581
+
3582
+ 1. It is not required to change all existing code to meet current style
3583
+ guidelines. Reformatting existing code is a trade-off between code churn and
3584
+ consistency. Style rules evolve over time and these kinds of tweaks to
3585
+ maintain compliance would create unnecessary churn. However, if significant
3586
+ changes are being made to a file it is expected that the file will be in
3587
+ Google Style.
3588
+ 2. Be careful not to allow opportunistic style fixes to muddle the focus of a
3589
+ CL. If you find yourself making a lot of style changes that aren’t critical
3590
+ to the central focus of a CL, promote those changes to a separate CL.
3591
+
3592
+ ### Deprecation
3593
+
3594
+ Mark deprecated methods, classes or interfaces with an `@deprecated` JSDoc
3595
+ annotation. A deprecation comment must include simple, clear directions for
3596
+ people to fix their call sites.
3597
+
3598
+ ### Generated code: mostly exempt
3599
+
3600
+ Source code generated by the build process is not required to be in Google
3601
+ Style. However, any generated identifiers that will be referenced from
3602
+ hand-written source code must follow the naming requirements. As a special
3603
+ exception, such identifiers are allowed to contain underscores, which may help
3604
+ to avoid conflicts with hand-written identifiers.
3605
+
3606
+ #### Style guide goals
3607
+
3608
+ In general, engineers usually know best about what's needed in their code, so if
3609
+ there are multiple options and the choice is situation dependent, we should let
3610
+ decisions be made locally. So the default answer should be "leave it out".
3611
+
3612
+ The following points are the exceptions, which are the reasons we have some
3613
+ global rules. Evaluate your style guide proposal against the following:
3614
+
3615
+ 1. **Code should avoid patterns that are known to cause problems, especially
3616
+ for users new to the language.**
3617
+ 2. **Code across
3618
+ projects should be consistent across
3619
+ irrelevant variations.**
3620
+
3621
+ When there are two options that are equivalent in a superficial way, we
3622
+ should consider choosing one just so we don't divergently evolve for no
3623
+ reason and avoid pointless debates in code reviews.
3624
+
3625
+ Examples:
3626
+
3627
+ * The capitalization style of names.
3628
+ * `x as T` syntax vs the equivalent `<T>x` syntax (disallowed).
3629
+ * `Array<[number, number]>` vs `[number, number][]`.
3630
+ 3. **Code should be maintainable in the long term.**
3631
+
3632
+ Code usually lives longer than the original author works on it, and the
3633
+ TypeScript team must keep all of Google working into the future.
3634
+
3635
+ Examples:
3636
+
3637
+ * We use software to automate changes to code, so code is autoformatted so
3638
+ it's easy for software to meet whitespace rules.
3639
+ * We require a single set of compiler flags, so a given TS library can be
3640
+ written assuming a specific set of flags, and users can always safely
3641
+ use a shared library.
3642
+ * Code must import the libraries it uses ("strict deps") so that a
3643
+ refactor in a dependency doesn't change the dependencies of its users.
3644
+ * We ask users to write tests. Without tests we cannot have confidence
3645
+ that changes that we make to the language, don't break users.
3646
+ 4. **Code reviewers should be focused on improving the quality of the code, not
3647
+ enforcing arbitrary rules.**
3648
+
3649
+ If it's possible to implement your rule as an
3650
+ automated check that is often a good sign.
3651
+ This also supports principle 3.
3652
+
3653
+ If it really just doesn't matter that much -- if it's an obscure corner of
3654
+ the language or if it avoids a bug that is unlikely to occur -- it's
3655
+ probably worth leaving out.
3656
+
3657
+ ---
3658
+
3659
+ 1. Namespace imports are often called 'module imports' [↩](#fnref1)
3660
+ 2. named imports are sometimes called 'destructuring
3661
+ imports' because they use similar syntax to
3662
+ destructuring assignments. [↩](#fnref2)