diff --git a/packages/eslint-plugin/src/rules/typedef.ts b/packages/eslint-plugin/src/rules/typedef.ts index e47ccad9522..3c535467f2c 100644 --- a/packages/eslint-plugin/src/rules/typedef.ts +++ b/packages/eslint-plugin/src/rules/typedef.ts @@ -142,7 +142,32 @@ export default util.createRule<[Options], MessageIds>({ options[OptionKeys.VariableDeclaration] && !node.id.typeAnnotation ) { - report(node, getNodeName(node.id)); + // Are we inside a context that does not allow type annotations? + let typeAnnotationRequired = true; + + let current: TSESTree.Node | undefined = node.parent; + while (current) { + switch (current.type) { + case AST_NODE_TYPES.VariableDeclaration: + // Keep looking upwards + current = current.parent; + break; + case AST_NODE_TYPES.ForOfStatement: + case AST_NODE_TYPES.ForInStatement: + // Stop traversing and don't report an error + typeAnnotationRequired = false; + current = undefined; + break; + default: + // Stop traversing + current = undefined; + break; + } + } + + if (typeAnnotationRequired) { + report(node, getNodeName(node.id)); + } } }, }; diff --git a/packages/eslint-plugin/tests/rules/typedef.test.ts b/packages/eslint-plugin/tests/rules/typedef.test.ts index 49d98e2654f..b1a7b08bcf0 100644 --- a/packages/eslint-plugin/tests/rules/typedef.test.ts +++ b/packages/eslint-plugin/tests/rules/typedef.test.ts @@ -198,6 +198,31 @@ ruleTester.run('typedef', rule, { }, ], }, + // Contexts where TypeScript doesn't allow annotations + { + code: `for (x of [1, 2, 3]) { }`, + options: [ + { + variableDeclaration: true, + }, + ], + }, + { + code: `for (const x in {}) { }`, + options: [ + { + variableDeclaration: true, + }, + ], + }, + { + code: `try { } catch (e) { }`, + options: [ + { + variableDeclaration: true, + }, + ], + }, ], invalid: [ // Array destructuring