Skip to content

Commit 660bace

Browse files
authoredFeb 19, 2020
fix(eslint-plugin): [typedef] allow array/object destructuring in for/of (#1570)
1 parent 0d8e87e commit 660bace

File tree

3 files changed

+89
-2
lines changed

3 files changed

+89
-2
lines changed
 

‎packages/eslint-plugin/docs/rules/typedef.md

+6
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ Examples of **correct** code with `{ "arrayDestructuring": true }`:
7676
const [a]: number[] = [1];
7777
const [b]: [number] = [2];
7878
const [c, d]: [boolean, string] = [true, 'text'];
79+
80+
for (const [key, val] of new Map([['key', 1]])) {
81+
}
7982
```
8083

8184
### `arrowParameter`
@@ -144,6 +147,9 @@ Examples of **correct** code with `{ "objectDestructuring": true }`:
144147
```ts
145148
const { length }: { length: number } = 'text';
146149
const [b, c]: [number, number] = Math.random() ? [1, 2] : [3, 4];
150+
151+
for (const { key, val } of [{ key: 'key', val: 1 }]) {
152+
}
147153
```
148154

149155
### `parameter`

‎packages/eslint-plugin/src/rules/typedef.ts

+35-2
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,31 @@ export default util.createRule<[Options], MessageIds>({
6969
return node.type === AST_NODE_TYPES.Identifier ? node.name : undefined;
7070
}
7171

72+
function isForOfStatementContext(
73+
node: TSESTree.ArrayPattern | TSESTree.ObjectPattern,
74+
): boolean {
75+
let current: TSESTree.Node | undefined = node.parent;
76+
while (current) {
77+
switch (current.type) {
78+
case AST_NODE_TYPES.VariableDeclarator:
79+
case AST_NODE_TYPES.VariableDeclaration:
80+
case AST_NODE_TYPES.ObjectPattern:
81+
case AST_NODE_TYPES.ArrayPattern:
82+
case AST_NODE_TYPES.Property:
83+
current = current.parent;
84+
break;
85+
86+
case AST_NODE_TYPES.ForOfStatement:
87+
return true;
88+
89+
default:
90+
current = undefined;
91+
}
92+
}
93+
94+
return false;
95+
}
96+
7297
function checkParameters(params: TSESTree.Parameter[]): void {
7398
for (const param of params) {
7499
let annotationNode: TSESTree.Node | undefined;
@@ -102,7 +127,11 @@ export default util.createRule<[Options], MessageIds>({
102127

103128
return {
104129
ArrayPattern(node): void {
105-
if (options[OptionKeys.ArrayDestructuring] && !node.typeAnnotation) {
130+
if (
131+
options[OptionKeys.ArrayDestructuring] &&
132+
!node.typeAnnotation &&
133+
!isForOfStatementContext(node)
134+
) {
106135
report(node);
107136
}
108137
},
@@ -132,7 +161,11 @@ export default util.createRule<[Options], MessageIds>({
132161
}
133162
},
134163
ObjectPattern(node): void {
135-
if (options[OptionKeys.ObjectDestructuring] && !node.typeAnnotation) {
164+
if (
165+
options[OptionKeys.ObjectDestructuring] &&
166+
!node.typeAnnotation &&
167+
!isForOfStatementContext(node)
168+
) {
136169
report(node);
137170
}
138171
},

‎packages/eslint-plugin/tests/rules/typedef.test.ts

+48
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,30 @@ ruleTester.run('typedef', rule, {
3838
},
3939
],
4040
},
41+
{
42+
code: `for (const [key, val] of new Map([['key', 1]])) {}`,
43+
options: [
44+
{
45+
arrayDestructuring: true,
46+
},
47+
],
48+
},
49+
{
50+
code: `for (const [[key]] of [[['key']]]) {}`,
51+
options: [
52+
{
53+
arrayDestructuring: true,
54+
},
55+
],
56+
},
57+
{
58+
code: `for (const [[{ key }]] of [[[{ key: 'value' }]]]) {}`,
59+
options: [
60+
{
61+
arrayDestructuring: true,
62+
},
63+
],
64+
},
4165
`let a: number;
4266
[a] = [1];`,
4367
// Arrow parameters
@@ -93,6 +117,22 @@ ruleTester.run('typedef', rule, {
93117
},
94118
],
95119
},
120+
{
121+
code: `for (const {p1: {p2: { p3 }}} of [{p1: {p2: {p3: 'value'}}}]) {}`,
122+
options: [
123+
{
124+
objectDestructuring: true,
125+
},
126+
],
127+
},
128+
{
129+
code: `for (const {p1: {p2: { p3: [key] }}} of [{p1: {p2: {p3: ['value']}}}]) {}`,
130+
options: [
131+
{
132+
objectDestructuring: true,
133+
},
134+
],
135+
},
96136
{
97137
code: `const { a } = { a: 1 };`,
98138
options: [
@@ -101,6 +141,14 @@ ruleTester.run('typedef', rule, {
101141
},
102142
],
103143
},
144+
{
145+
code: `for (const { key, val } of [{ key: 'key', val: 1 }]) {}`,
146+
options: [
147+
{
148+
objectDestructuring: true,
149+
},
150+
],
151+
},
104152
// Function parameters
105153
`function receivesNumber(a: number): void { }`,
106154
`function receivesStrings(a: string, b: string): void { }`,

0 commit comments

Comments
 (0)
Please sign in to comment.