Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b5a52a3

Browse files
sveyretbradzacher
andcommitted
feat(eslint-plugin): [member-ordering] add index signature (typescript-eslint#1190)
Co-authored-by: Brad Zacher <[email protected]>
1 parent 39f654b commit b5a52a3

File tree

4 files changed

+298
-89
lines changed

4 files changed

+298
-89
lines changed

packages/eslint-plugin/docs/rules/member-ordering.md

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ It allows to group members by their type (e.g. `public-static-field`, `protected
1717
classes?: Array<MemberType> | never
1818
classExpressions?: Array<MemberType> | never
1919

20-
interfaces?: ['field' | 'method' | 'constructor'] | never
21-
typeLiterals?: ['field' | 'method' | 'constructor'] | never
20+
interfaces?: ['signature' | 'field' | 'method' | 'constructor'] | never
21+
typeLiterals?: ['signature' | 'field' | 'method' | 'constructor'] | never
2222
}
2323
```
2424

@@ -30,6 +30,9 @@ There are multiple ways to specify the member types. The most explicit and granu
3030

3131
```json5
3232
[
33+
// Index signature
34+
'signature',
35+
3336
// Fields
3437
'public-static-field',
3538
'protected-static-field',
@@ -67,6 +70,9 @@ It is also possible to group member types by their accessibility (`static`, `ins
6770

6871
```json5
6972
[
73+
// Index signature
74+
// No accessibility for index signature. See above.
75+
7076
// Fields
7177
'public-field', // = ['public-static-field', 'public-instance-field'])
7278
'protected-field', // = ['protected-static-field', 'protected-instance-field'])
@@ -88,6 +94,9 @@ Another option is to group the member types by their scope (`public`, `protected
8894

8995
```json5
9096
[
97+
// Index signature
98+
// No scope for index signature. See above.
99+
91100
// Fields
92101
'static-field', // = ['public-static-field', 'protected-static-field', 'private-static-field'])
93102
'instance-field', // = ['public-instance-field', 'protected-instance-field', 'private-instance-field'])
@@ -109,6 +118,9 @@ The third grouping option is to ignore both scope and accessibility.
109118

110119
```json5
111120
[
121+
// Index signature
122+
// No grouping for index signature. See above.
123+
112124
// Fields
113125
'field', // = ['public-static-field', 'protected-static-field', 'private-static-field', 'public-instance-field', 'protected-instance-field', 'private-instance-field',
114126
// 'public-abstract-field', 'protected-abstract-field', private-abstract-field'])
@@ -129,6 +141,8 @@ The default configuration looks as follows:
129141
```json
130142
{
131143
"default": [
144+
"signature",
145+
132146
"public-static-field",
133147
"protected-static-field",
134148
"private-static-field",
@@ -186,7 +200,7 @@ Note: The default configuration contains member group types which contain other
186200

187201
Note: The `default` options are overwritten in these examples.
188202

189-
#### Configuration: `{ "default": ["method", "constructor", "field"] }`
203+
#### Configuration: `{ "default": ["signature", "method", "constructor", "field"] }`
190204

191205
##### Incorrect examples
192206

@@ -197,6 +211,8 @@ interface Foo {
197211
new (); // -> constructor
198212

199213
A(): void; // -> method
214+
215+
[Z: string]: any; // -> signature
200216
}
201217
```
202218

@@ -209,6 +225,8 @@ type Foo = {
209225
// no constructor
210226

211227
A(): void; // -> method
228+
229+
// no signature
212230
};
213231
```
214232

@@ -224,10 +242,12 @@ class Foo {
224242

225243
public static A(): void {} // -> method
226244
public B(): void {} // -> method
245+
246+
[Z: string]: any; // -> signature
227247
}
228248
```
229249

230-
Note: Accessibility or scope are ignored with this ignored.
250+
Note: Accessibility or scope are ignored with this configuration.
231251

232252
```ts
233253
const Foo = class {
@@ -239,6 +259,8 @@ const Foo = class {
239259
public static A(): void {} // -> method
240260
public B(): void {} // -> method
241261

262+
[Z: string]: any; // -> signature
263+
242264
protected static E: string; // -> field
243265
};
244266
```
@@ -249,6 +271,8 @@ Note: Not all members have to be grouped to find rule violations.
249271

250272
```ts
251273
interface Foo {
274+
[Z: string]: any; // -> signature
275+
252276
A(): void; // -> method
253277

254278
new (); // -> constructor
@@ -259,6 +283,8 @@ interface Foo {
259283

260284
```ts
261285
type Foo = {
286+
// no signature
287+
262288
A(): void; // -> method
263289

264290
// no constructor
@@ -269,6 +295,8 @@ type Foo = {
269295

270296
```ts
271297
class Foo {
298+
[Z: string]: any; // -> signature
299+
272300
public static A(): void {} // -> method
273301
public B(): void {} // -> method
274302

@@ -282,6 +310,8 @@ class Foo {
282310

283311
```ts
284312
const Foo = class {
313+
[Z: string]: any; // -> signature
314+
285315
public static A(): void {} // -> method
286316
public B(): void {} // -> method
287317

@@ -311,6 +341,8 @@ class Foo {
311341

312342
public static A(): void {} // (irrelevant)
313343

344+
[Z: string]: any; // (irrelevant)
345+
314346
public B(): void {} // -> public instance method
315347
}
316348
```
@@ -321,6 +353,8 @@ Note: Public instance methods should come first before public static fields. Eve
321353
const Foo = class {
322354
private C: string; // (irrelevant)
323355

356+
[Z: string]: any; // (irrelevant)
357+
324358
public static E: string; // -> public static field
325359

326360
public D: string; // (irrelevant)
@@ -350,6 +384,8 @@ class Foo {
350384
constructor() {} // (irrelevant)
351385

352386
public static A(): void {} // (irrelevant)
387+
388+
[Z: string]: any; // (irrelevant)
353389
}
354390
```
355391

@@ -359,6 +395,8 @@ const Foo = class {
359395

360396
private C: string; // (irrelevant)
361397

398+
[Z: string]: any; // (irrelevant)
399+
362400
public D: string; // (irrelevant)
363401

364402
constructor() {} // (irrelevant)
@@ -384,6 +422,8 @@ class Foo {
384422
private static D: string; // -> static field
385423

386424
public static A: string; // -> public static field
425+
426+
[Z: string]: any; // (irrelevant)
387427
}
388428
```
389429

@@ -402,6 +442,8 @@ const foo = class {
402442
protected static C: string; // -> static field
403443
private static D: string; // -> static field
404444

445+
[Z: string]: any; // (irrelevant)
446+
405447
public static A: string; // -> public static field
406448
};
407449
```
@@ -424,6 +466,8 @@ class Foo {
424466

425467
```ts
426468
const foo = class {
469+
[Z: string]: any; // -> signature
470+
427471
public static A: string; // -> public static field
428472

429473
constructor() {} // -> constructor
@@ -596,11 +640,11 @@ const foo = class {
596640

597641
Note: If this is not set, the `default` will automatically be applied to classes expressions as well. If a `interfaces` configuration is provided, only this configuration will be used for `interfaces` (i.e. nothing will be merged with `default`).
598642

599-
Note: The configuration for `interfaces` only allows a limited set of member types: `field`, `constructor` and `method`.
643+
Note: The configuration for `interfaces` only allows a limited set of member types: `signature`, `field`, `constructor` and `method`.
600644

601645
Note: The configuration for `interfaces` does not apply to type literals (use `typeLiterals` for them).
602646

603-
#### Configuration: `{ "interfaces": ["method", "constructor", "field"] }`
647+
#### Configuration: `{ "interfaces": ["signature", "method", "constructor", "field"] }`
604648

605649
##### Incorrect example
606650

@@ -611,13 +655,17 @@ interface Foo {
611655
new (); // -> constructor
612656

613657
A(): void; // -> method
658+
659+
[Z: string]: any; // -> signature
614660
}
615661
```
616662

617663
##### Correct example
618664

619665
```ts
620666
interface Foo {
667+
[Z: string]: any; // -> signature
668+
621669
A(): void; // -> method
622670

623671
new (); // -> constructor
@@ -630,11 +678,11 @@ interface Foo {
630678

631679
Note: If this is not set, the `default` will automatically be applied to classes expressions as well. If a `typeLiterals` configuration is provided, only this configuration will be used for `typeLiterals` (i.e. nothing will be merged with `default`).
632680

633-
Note: The configuration for `typeLiterals` only allows a limited set of member types: `field`, `constructor` and `method`.
681+
Note: The configuration for `typeLiterals` only allows a limited set of member types: `signature`, `field`, `constructor` and `method`.
634682

635-
Note: The configuration for `typeLiterals` does not apply to type literals (use `interfaces` for them).
683+
Note: The configuration for `typeLiterals` does not apply to interfaces (use `interfaces` for them).
636684

637-
#### Configuration: `{ "typeLiterals": ["method", "constructor", "field"] }`
685+
#### Configuration: `{ "typeLiterals": ["signature", "method", "constructor", "field"] }`
638686

639687
##### Incorrect example
640688

@@ -645,13 +693,17 @@ type Foo = {
645693
A(): void; // -> method
646694

647695
new (); // -> constructor
696+
697+
[Z: string]: any; // -> signature
648698
};
649699
```
650700

651701
##### Correct example
652702

653703
```ts
654704
type Foo = {
705+
[Z: string]: any; // -> signature
706+
655707
A(): void; // -> method
656708

657709
new (); // -> constructor

packages/eslint-plugin/src/rules/member-ordering.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ const allMemberTypes = ['field', 'method', 'constructor'].reduce<string[]>(
3939
},
4040
[],
4141
);
42+
allMemberTypes.unshift('signature');
4243

4344
export default util.createRule<Options, MessageIds>({
4445
name: 'member-ordering',
@@ -104,7 +105,7 @@ export default util.createRule<Options, MessageIds>({
104105
{
105106
type: 'array',
106107
items: {
107-
enum: ['field', 'method', 'constructor'],
108+
enum: ['signature', 'field', 'method', 'constructor'],
108109
},
109110
},
110111
],
@@ -117,7 +118,7 @@ export default util.createRule<Options, MessageIds>({
117118
{
118119
type: 'array',
119120
items: {
120-
enum: ['field', 'method', 'constructor'],
121+
enum: ['signature', 'field', 'method', 'constructor'],
121122
},
122123
},
123124
],
@@ -130,6 +131,8 @@ export default util.createRule<Options, MessageIds>({
130131
defaultOptions: [
131132
{
132133
default: [
134+
'signature',
135+
133136
'public-static-field',
134137
'protected-static-field',
135138
'private-static-field',
@@ -194,7 +197,6 @@ export default util.createRule<Options, MessageIds>({
194197
node: TSESTree.ClassElement | TSESTree.TypeElement,
195198
): string | null {
196199
// TODO: add missing TSCallSignatureDeclaration
197-
// TODO: add missing TSIndexSignature
198200
switch (node.type) {
199201
case AST_NODE_TYPES.TSAbstractMethodDefinition:
200202
case AST_NODE_TYPES.MethodDefinition:
@@ -210,6 +212,8 @@ export default util.createRule<Options, MessageIds>({
210212
: 'field';
211213
case AST_NODE_TYPES.TSPropertySignature:
212214
return 'field';
215+
case AST_NODE_TYPES.TSIndexSignature:
216+
return 'signature';
213217
default:
214218
return null;
215219
}
@@ -235,6 +239,8 @@ export default util.createRule<Options, MessageIds>({
235239
: util.getNameFromClassMember(node, sourceCode);
236240
case AST_NODE_TYPES.TSConstructSignatureDeclaration:
237241
return 'new';
242+
case AST_NODE_TYPES.TSIndexSignature:
243+
return util.getNameFromIndexSignature(node);
238244
default:
239245
return null;
240246
}

packages/eslint-plugin/src/util/misc.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,19 @@ type InferMessageIdsTypeFromRule<T> = T extends TSESLint.RuleModule<
4848
? TMessageIds
4949
: unknown;
5050

51+
/**
52+
* Gets a string representation of the name of the index signature.
53+
*/
54+
export function getNameFromIndexSignature(
55+
node: TSESTree.TSIndexSignature,
56+
): string {
57+
const propName: TSESTree.PropertyName | undefined = node.parameters.find(
58+
(parameter: TSESTree.Parameter): parameter is TSESTree.Identifier =>
59+
parameter.type === AST_NODE_TYPES.Identifier,
60+
);
61+
return propName ? getNameFromPropertyName(propName) : '(index signature)';
62+
}
63+
5164
/**
5265
* Gets a string name representation of the given PropertyName node
5366
*/

0 commit comments

Comments
 (0)