Skip to content

Commit 156d058

Browse files
authored
feat(eslint-plugin): [naming-convention] allow selecting only const variables (typescript-eslint#2291)
1 parent 2c90d9f commit 156d058

File tree

3 files changed

+56
-10
lines changed

3 files changed

+56
-10
lines changed

packages/eslint-plugin/docs/rules/naming-convention.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ There are two types of selectors, individual selectors, and grouped selectors.
192192
Individual Selectors match specific, well-defined sets. There is no overlap between each of the individual selectors.
193193

194194
- `variable` - matches any `var` / `let` / `const` variable name.
195-
- Allowed `modifiers`: none.
195+
- Allowed `modifiers`: `const`.
196196
- Allowed `types`: `boolean`, `string`, `number`, `function`, `array`.
197197
- `function` - matches any named function declaration or named function expression.
198198
- Allowed `modifiers`: none.
@@ -309,6 +309,21 @@ Group Selectors are provided for convenience, and essentially bundle up sets of
309309
}
310310
```
311311

312+
### Enforce that all const variables are in UPPER_CASE
313+
314+
```json
315+
{
316+
"@typescript-eslint/naming-convention": [
317+
"error",
318+
{
319+
"selector": "variable",
320+
"modifiers": ["const"],
321+
"format": ["UPPER_CASE"]
322+
}
323+
]
324+
}
325+
```
326+
312327
### Enforce that type parameters (generics) are prefixed with `T`
313328

314329
This allows you to emulate the old `generic-type-naming` rule.

packages/eslint-plugin/src/rules/naming-convention.ts

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,13 @@ type MetaSelectorsString = keyof typeof MetaSelectors;
8080
type IndividualAndMetaSelectorsString = SelectorsString | MetaSelectorsString;
8181

8282
enum Modifiers {
83-
readonly = 1 << 0,
84-
static = 1 << 1,
85-
public = 1 << 2,
86-
protected = 1 << 3,
87-
private = 1 << 4,
88-
abstract = 1 << 5,
83+
const = 1 << 0,
84+
readonly = 1 << 1,
85+
static = 1 << 2,
86+
public = 1 << 3,
87+
protected = 1 << 4,
88+
private = 1 << 5,
89+
abstract = 1 << 6,
8990
}
9091
type ModifiersString = keyof typeof Modifiers;
9192

@@ -255,7 +256,7 @@ const SCHEMA: JSONSchema.JSONSchema4 = {
255256
...selectorSchema('default', false, util.getEnumNames(Modifiers)),
256257

257258
...selectorSchema('variableLike', false),
258-
...selectorSchema('variable', true),
259+
...selectorSchema('variable', true, ['const']),
259260
...selectorSchema('function', false),
260261
...selectorSchema('parameter', true),
261262

@@ -439,8 +440,18 @@ export default util.createRule<Options, MessageIds>({
439440
const identifiers: TSESTree.Identifier[] = [];
440441
getIdentifiersFromPattern(node.id, identifiers);
441442

443+
const modifiers = new Set<Modifiers>();
444+
const parent = node.parent;
445+
if (
446+
parent &&
447+
parent.type === AST_NODE_TYPES.VariableDeclaration &&
448+
parent.kind === 'const'
449+
) {
450+
modifiers.add(Modifiers.const);
451+
}
452+
442453
identifiers.forEach(i => {
443-
validator(i);
454+
validator(i, modifiers);
444455
});
445456
},
446457

packages/eslint-plugin/tests/rules/naming-convention.test.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,10 @@ ruleTester.run('naming-convention', rule, {
626626
},
627627
{
628628
code: `
629+
declare const ANY_UPPER_CASE: any;
630+
declare const ANY_UPPER_CASE: any | null;
631+
declare const ANY_UPPER_CASE: any | null | undefined;
632+
629633
declare const string_camelCase: string;
630634
declare const string_camelCase: string | null;
631635
declare const string_camelCase: string | null | undefined;
@@ -647,6 +651,12 @@ ruleTester.run('naming-convention', rule, {
647651
`,
648652
parserOptions,
649653
options: [
654+
{
655+
selector: 'variable',
656+
modifiers: ['const'],
657+
format: ['UPPER_CASE'],
658+
prefix: ['ANY_'],
659+
},
650660
{
651661
selector: 'variable',
652662
types: ['string'],
@@ -824,6 +834,10 @@ ruleTester.run('naming-convention', rule, {
824834
},
825835
{
826836
code: `
837+
declare const any_camelCase01: any;
838+
declare const any_camelCase02: any | null;
839+
declare const any_camelCase03: any | null | undefined;
840+
827841
declare const string_camelCase01: string;
828842
declare const string_camelCase02: string | null;
829843
declare const string_camelCase03: string | null | undefined;
@@ -844,6 +858,12 @@ ruleTester.run('naming-convention', rule, {
844858
declare const boolean_camelCase16: true | false | null | undefined;
845859
`,
846860
options: [
861+
{
862+
selector: 'variable',
863+
modifiers: ['const'],
864+
format: ['UPPER_CASE'],
865+
prefix: ['any_'],
866+
},
847867
{
848868
selector: 'variable',
849869
types: ['string'],
@@ -864,7 +884,7 @@ ruleTester.run('naming-convention', rule, {
864884
},
865885
],
866886
parserOptions,
867-
errors: Array(16).fill({ messageId: 'doesNotMatchFormatTrimmed' }),
887+
errors: Array(19).fill({ messageId: 'doesNotMatchFormatTrimmed' }),
868888
},
869889
{
870890
code: `

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy