0
# Code Quality and Consistency
1
2
Rules that prevent common stylistic issues and enforce consistent patterns across codebases.
3
4
## no-extra-parens
5
6
Disallows unnecessary parentheses.
7
8
```javascript { .api }
9
const noExtraParens: Rule.RuleModule;
10
11
// Rule options
12
type NoExtraParensOptions =
13
| 'all'
14
| 'functions'
15
| ['all' | 'functions', {
16
conditionalAssign?: boolean;
17
returnAssign?: boolean;
18
nestedBinaryExpressions?: boolean;
19
ignoreJSX?: 'none' | 'all' | 'single-line' | 'multi-line';
20
enforceForArrowConditionals?: boolean;
21
enforceForSequenceExpressions?: boolean;
22
enforceForNewInMemberExpressions?: boolean;
23
enforceForFunctionPrototypeMethods?: boolean;
24
}];
25
```
26
27
**Usage Examples:**
28
29
```javascript
30
// ✗ Bad - unnecessary parentheses
31
const result = (a + b);
32
if ((condition)) {
33
doSomething();
34
}
35
const func = (function() { return true; });
36
37
// ✓ Good - necessary parentheses only
38
const result = a + b;
39
if (condition) {
40
doSomething();
41
}
42
const func = function() { return true; };
43
44
// ✓ Good - parentheses needed for precedence
45
const result = (a + b) * c;
46
const condition = (x === 1) || (y === 2);
47
48
// ✓ Good with { conditionalAssign: false }
49
let result;
50
if ((result = getValue())) { // parens allowed for assignment
51
process(result);
52
}
53
```
54
55
**Configuration:**
56
57
```javascript
58
rules: {
59
'@stylistic/js/no-extra-parens': ['error', 'all', { ignoreJSX: 'all' }]
60
}
61
```
62
63
## no-extra-semi
64
65
Disallows unnecessary semicolons.
66
67
```javascript { .api }
68
const noExtraSemi: Rule.RuleModule;
69
70
// No options
71
```
72
73
**Usage Examples:**
74
75
```javascript
76
// ✗ Bad - extra semicolons
77
function example() {
78
return true;;
79
}
80
81
const obj = {
82
name: 'John';
83
};
84
85
class Example {
86
method() {
87
return true;;
88
};
89
}
90
91
// ✓ Good - necessary semicolons only
92
function example() {
93
return true;
94
}
95
96
const obj = {
97
name: 'John'
98
};
99
100
class Example {
101
method() {
102
return true;
103
}
104
}
105
```
106
107
**Configuration:**
108
109
```javascript
110
rules: {
111
'@stylistic/js/no-extra-semi': 'error'
112
}
113
```
114
115
## no-mixed-spaces-and-tabs
116
117
Disallows mixed spaces and tabs for indentation.
118
119
```javascript { .api }
120
const noMixedSpacesAndTabs: Rule.RuleModule;
121
122
// Rule options
123
type NoMixedSpacesAndTabsOptions = 'smart-tabs' | boolean;
124
```
125
126
**Usage Examples:**
127
128
```javascript
129
// ✗ Bad - mixing spaces and tabs
130
function example() {
131
⇥ return true; // spaces followed by tab
132
}
133
134
// ✓ Good - consistent spaces
135
function example() {
136
return true;
137
}
138
139
// ✓ Good - consistent tabs
140
function example() {
141
⇥ return true;
142
}
143
144
// ✓ Good with "smart-tabs" - tabs for indentation, spaces for alignment
145
function example() {
146
⇥ const items = [
147
⇥ 'apple', // tab for indent, spaces for alignment
148
⇥ 'banana'
149
⇥ ];
150
}
151
```
152
153
**Configuration:**
154
155
```javascript
156
rules: {
157
'@stylistic/js/no-mixed-spaces-and-tabs': 'error'
158
}
159
```
160
161
## no-trailing-spaces
162
163
Disallows trailing whitespace at the end of lines.
164
165
```javascript { .api }
166
const noTrailingSpaces: Rule.RuleModule;
167
168
// Rule options
169
type NoTrailingSpacesOptions = {
170
skipBlankLines?: boolean;
171
ignoreComments?: boolean;
172
};
173
```
174
175
**Usage Examples:**
176
177
```javascript
178
// ✗ Bad - trailing spaces
179
const name = 'John';
180
const age = 30;
181
182
// ✓ Good - no trailing spaces
183
const name = 'John';
184
const age = 30;
185
186
// ✓ Good with skipBlankLines: true
187
const name = 'John';
188
// blank line with spaces OK
189
const age = 30;
190
191
// ✓ Good with ignoreComments: true
192
const name = 'John'; // comment with trailing spaces
193
```
194
195
**Configuration:**
196
197
```javascript
198
rules: {
199
'@stylistic/js/no-trailing-spaces': ['error', { skipBlankLines: true }]
200
}
201
```
202
203
## no-multi-spaces
204
205
Disallows multiple spaces.
206
207
```javascript { .api }
208
const noMultiSpaces: Rule.RuleModule;
209
210
// Rule options
211
type NoMultiSpacesOptions = {
212
exceptions?: {
213
[nodeType: string]: boolean;
214
};
215
ignoreEOLComments?: boolean;
216
};
217
```
218
219
**Usage Examples:**
220
221
```javascript
222
// ✗ Bad - multiple spaces
223
const name = 'John';
224
if (condition && other) {
225
doSomething();
226
}
227
228
// ✓ Good - single spaces
229
const name = 'John';
230
if (condition && other) {
231
doSomething();
232
}
233
234
// ✓ Good with exceptions: { Property: true }
235
const obj = {
236
name : 'John', // multiple spaces allowed in properties
237
age : 30
238
};
239
240
// ✓ Good with ignoreEOLComments: true
241
const value = 1; // multiple spaces before EOL comment OK
242
```
243
244
**Configuration:**
245
246
```javascript
247
rules: {
248
'@stylistic/js/no-multi-spaces': ['error', {
249
exceptions: { Property: true },
250
ignoreEOLComments: true
251
}]
252
}
253
```
254
255
## no-whitespace-before-property
256
257
Disallows whitespace before properties.
258
259
```javascript { .api }
260
const noWhitespaceBeforeProperty: Rule.RuleModule;
261
262
// No options
263
```
264
265
**Usage Examples:**
266
267
```javascript
268
// ✗ Bad - whitespace before property
269
const value = obj .property;
270
const result = user ['name'];
271
const method = obj .method();
272
273
// ✓ Good - no whitespace before property
274
const value = obj.property;
275
const result = user['name'];
276
const method = obj.method();
277
278
// Computed properties and method calls
279
const dynamic = obj[key];
280
const chained = obj.method().property;
281
```
282
283
**Configuration:**
284
285
```javascript
286
rules: {
287
'@stylistic/js/no-whitespace-before-property': 'error'
288
}
289
```
290
291
## max-len
292
293
Enforces a maximum line length.
294
295
```javascript { .api }
296
const maxLen: Rule.RuleModule;
297
298
// Rule options
299
type MaxLenOptions =
300
| number
301
| {
302
code?: number;
303
tabWidth?: number;
304
comments?: number;
305
ignorePattern?: string;
306
ignoreComments?: boolean;
307
ignoreTrailingComments?: boolean;
308
ignoreUrls?: boolean;
309
ignoreStrings?: boolean;
310
ignoreTemplateLiterals?: boolean;
311
ignoreRegExpLiterals?: boolean;
312
};
313
```
314
315
**Usage Examples:**
316
317
```javascript
318
// ✗ Bad with code: 80
319
const veryLongVariableNameThatExceedsTheMaximumLineLengthAndShouldBeWrapped = 'value';
320
321
// ✓ Good with code: 80
322
const longVariableName = 'value';
323
const message = 'This is a shorter line that fits within the limit';
324
325
// ✓ Good with ignoreUrls: true
326
const url = 'https://this-is-a-very-long-url-that-would-normally-exceed-the-line-length-limit.com/path'; // URL ignored
327
328
// ✓ Good with ignoreStrings: true
329
const longString = 'This is a very long string that would normally exceed the line length limit but is ignored'; // String ignored
330
```
331
332
**Configuration:**
333
334
```javascript
335
rules: {
336
'@stylistic/js/max-len': ['error', {
337
code: 100,
338
tabWidth: 2,
339
ignoreUrls: true,
340
ignoreStrings: true,
341
ignoreTemplateLiterals: true
342
}]
343
}
344
```
345
346
## max-statements-per-line
347
348
Enforces a maximum number of statements allowed per line.
349
350
```javascript { .api }
351
const maxStatementsPerLine: Rule.RuleModule;
352
353
// Rule options
354
type MaxStatementsPerLineOptions = {
355
max?: number;
356
};
357
```
358
359
**Usage Examples:**
360
361
```javascript
362
// ✗ Bad with max: 1 (default)
363
const a = 1; const b = 2;
364
if (condition) doSomething(); return;
365
366
// ✓ Good with max: 1
367
const a = 1;
368
const b = 2;
369
if (condition) {
370
doSomething();
371
}
372
return;
373
374
// ✓ Good with max: 2
375
const a = 1; const b = 2; // two statements OK
376
```
377
378
**Configuration:**
379
380
```javascript
381
rules: {
382
'@stylistic/js/max-statements-per-line': ['error', { max: 1 }]
383
}
384
```
385
386
## no-floating-decimal
387
388
Disallows leading or trailing decimal points in numeric literals.
389
390
```javascript { .api }
391
const noFloatingDecimal: Rule.RuleModule;
392
393
// No options
394
```
395
396
**Usage Examples:**
397
398
```javascript
399
// ✗ Bad - floating decimal points
400
const leading = .5;
401
const trailing = 2.;
402
403
// ✓ Good - complete decimal numbers
404
const leading = 0.5;
405
const trailing = 2.0;
406
const integer = 2;
407
const decimal = 1.5;
408
```
409
410
**Configuration:**
411
412
```javascript
413
rules: {
414
'@stylistic/js/no-floating-decimal': 'error'
415
}
416
```
417
418
## brace-style
419
420
Enforces consistent brace style for blocks.
421
422
```javascript { .api }
423
const braceStyle: Rule.RuleModule;
424
425
// Rule options
426
type BraceStyleOptions =
427
| '1tbs'
428
| 'stroustrup'
429
| 'allman'
430
| ['1tbs' | 'stroustrup' | 'allman', {
431
allowSingleLine?: boolean;
432
}];
433
```
434
435
**Usage Examples:**
436
437
```javascript
438
// ✓ Good with "1tbs" (default - One True Brace Style)
439
if (condition) {
440
doSomething();
441
} else {
442
doSomethingElse();
443
}
444
445
// ✓ Good with "stroustrup"
446
if (condition) {
447
doSomething();
448
}
449
else {
450
doSomethingElse();
451
}
452
453
// ✓ Good with "allman"
454
if (condition)
455
{
456
doSomething();
457
}
458
else
459
{
460
doSomethingElse();
461
}
462
463
// ✓ Good with allowSingleLine: true
464
if (condition) { doSomething(); }
465
```
466
467
**Configuration:**
468
469
```javascript
470
rules: {
471
'@stylistic/js/brace-style': ['error', '1tbs', { allowSingleLine: true }]
472
}
473
```
474
475
## Common Quality Combinations
476
477
### Strict Quality Rules
478
```javascript
479
rules: {
480
'@stylistic/js/no-extra-parens': ['error', 'all'],
481
'@stylistic/js/no-extra-semi': 'error',
482
'@stylistic/js/no-trailing-spaces': 'error',
483
'@stylistic/js/no-multi-spaces': 'error',
484
'@stylistic/js/max-len': ['error', { code: 80 }],
485
'@stylistic/js/max-statements-per-line': ['error', { max: 1 }]
486
}
487
```
488
489
### Relaxed Quality Rules
490
```javascript
491
rules: {
492
'@stylistic/js/no-extra-semi': 'error',
493
'@stylistic/js/no-trailing-spaces': ['error', { skipBlankLines: true }],
494
'@stylistic/js/no-multi-spaces': ['error', { ignoreEOLComments: true }],
495
'@stylistic/js/max-len': ['error', {
496
code: 120,
497
ignoreUrls: true,
498
ignoreStrings: true
499
}],
500
'@stylistic/js/brace-style': ['error', '1tbs', { allowSingleLine: true }]
501
}
502
```
503
504
## no-mixed-operators
505
506
Disallows mixed binary operators.
507
508
```javascript { .api }
509
const noMixedOperators: Rule.RuleModule;
510
511
// Rule options
512
type NoMixedOperatorsOptions = {
513
groups?: string[][];
514
allowSamePrecedence?: boolean;
515
};
516
```
517
518
**Usage Examples:**
519
520
```javascript
521
// ✗ Bad - mixed operators without parentheses
522
const result = a + b * c;
523
const condition = x && y || z;
524
525
// ✓ Good - use parentheses to clarify precedence
526
const result = a + (b * c);
527
const condition = (x && y) || z;
528
529
// ✓ Good - same operator
530
const sum = a + b + c;
531
const product = x * y * z;
532
533
// ✓ Good with allowSamePrecedence: true
534
const mixed = a * b / c; // same precedence operators OK
535
```
536
537
**Configuration:**
538
539
```javascript
540
rules: {
541
'@stylistic/js/no-mixed-operators': ['error', {
542
groups: [
543
['+', '-', '*', '/', '%', '**'],
544
['&', '|', '^', '~', '<<', '>>', '>>>'],
545
['==', '!=', '===', '!==', '>', '>=', '<', '<='],
546
['&&', '||'],
547
['in', 'instanceof']
548
],
549
allowSamePrecedence: true
550
}]
551
}
552
```
553
554
## wrap-iife
555
556
Requires parentheses around immediate function invocations.
557
558
```javascript { .api }
559
const wrapIife: Rule.RuleModule;
560
561
// Rule options
562
type WrapIifeOptions =
563
| 'outside'
564
| 'inside'
565
| 'any'
566
| ['outside' | 'inside' | 'any', {
567
functionPrototypeMethods?: boolean;
568
}];
569
```
570
571
**Usage Examples:**
572
573
```javascript
574
// ✓ Good with "outside" (default)
575
(function() {
576
console.log('IIFE');
577
})();
578
579
// ✓ Good with "inside"
580
(function() {
581
console.log('IIFE');
582
}());
583
584
// ✓ Good with "any"
585
(function() { console.log('IIFE'); })(); // either style OK
586
(function() { console.log('IIFE'); }());
587
588
// ✓ Good with functionPrototypeMethods: true
589
(function() {}.call(this)); // method calls wrapped
590
```
591
592
**Configuration:**
593
594
```javascript
595
rules: {
596
'@stylistic/js/wrap-iife': ['error', 'outside', {
597
functionPrototypeMethods: true
598
}]
599
}
600
```
601
602
## wrap-regex
603
604
Requires parenthesis around regex literals.
605
606
```javascript { .api }
607
const wrapRegex: Rule.RuleModule;
608
609
// No options
610
```
611
612
**Usage Examples:**
613
614
```javascript
615
// ✗ Bad - regex without parentheses
616
const result = /abc/.test(str);
617
618
// ✓ Good - regex wrapped in parentheses
619
const result = (/abc/).test(str);
620
621
// Assignment doesn't require wrapping
622
const pattern = /abc/;
623
const result = pattern.test(str);
624
```
625
626
**Configuration:**
627
628
```javascript
629
rules: {
630
'@stylistic/js/wrap-regex': 'error'
631
}
632
```
633
634
## Type Definitions
635
636
```typescript { .api }
637
interface QualityRules {
638
'no-extra-parens': Rule.RuleModule;
639
'no-extra-semi': Rule.RuleModule;
640
'no-mixed-spaces-and-tabs': Rule.RuleModule;
641
'no-trailing-spaces': Rule.RuleModule;
642
'no-multi-spaces': Rule.RuleModule;
643
'no-whitespace-before-property': Rule.RuleModule;
644
'max-len': Rule.RuleModule;
645
'max-statements-per-line': Rule.RuleModule;
646
'no-floating-decimal': Rule.RuleModule;
647
'brace-style': Rule.RuleModule;
648
'no-mixed-operators': Rule.RuleModule;
649
'wrap-iife': Rule.RuleModule;
650
'wrap-regex': Rule.RuleModule;
651
}
652
653
interface MaxLenConfig {
654
code?: number;
655
tabWidth?: number;
656
comments?: number;
657
ignorePattern?: string;
658
ignoreComments?: boolean;
659
ignoreTrailingComments?: boolean;
660
ignoreUrls?: boolean;
661
ignoreStrings?: boolean;
662
ignoreTemplateLiterals?: boolean;
663
ignoreRegExpLiterals?: boolean;
664
}
665
666
interface NoExtraParensConfig {
667
conditionalAssign?: boolean;
668
returnAssign?: boolean;
669
nestedBinaryExpressions?: boolean;
670
ignoreJSX?: 'none' | 'all' | 'single-line' | 'multi-line';
671
enforceForArrowConditionals?: boolean;
672
enforceForSequenceExpressions?: boolean;
673
enforceForNewInMemberExpressions?: boolean;
674
enforceForFunctionPrototypeMethods?: boolean;
675
}
676
```