diff --git a/packages/eslint-plugin/docs/rules/no-shadow.md b/packages/eslint-plugin/docs/rules/no-shadow.md index ed241b80788..bcb40d4fb5a 100644 --- a/packages/eslint-plugin/docs/rules/no-shadow.md +++ b/packages/eslint-plugin/docs/rules/no-shadow.md @@ -3,7 +3,7 @@ ## Rule Details This rule extends the base [`eslint/no-shadow`](https://eslint.org/docs/rules/no-shadow) rule. -It adds support for TypeScript's `this` parameters, and adds options for TypeScript features. +It adds support for TypeScript's `this` parameters and global augmentation, and adds options for TypeScript features. ## How to use diff --git a/packages/eslint-plugin/src/rules/no-shadow.ts b/packages/eslint-plugin/src/rules/no-shadow.ts index 05761572b21..1d1f894b651 100644 --- a/packages/eslint-plugin/src/rules/no-shadow.ts +++ b/packages/eslint-plugin/src/rules/no-shadow.ts @@ -3,6 +3,7 @@ import { TSESLint, AST_NODE_TYPES, } from '@typescript-eslint/experimental-utils'; +import { ScopeType } from '@typescript-eslint/scope-manager'; import * as util from '../util'; type MessageIds = 'noShadow'; @@ -67,6 +68,16 @@ export default util.createRule({ }, ], create(context, [options]) { + /** + * Check if a scope is a TypeScript module augmenting the global namespace. + */ + function isGlobalAugmentation(scope: TSESLint.Scope.Scope): boolean { + return ( + (scope.type === ScopeType.tsModule && !!scope.block.global) || + (!!scope.upper && isGlobalAugmentation(scope.upper)) + ); + } + /** * Check if variable is a `this` parameter. */ @@ -261,6 +272,11 @@ export default util.createRule({ * @param {Scope} scope Fixme */ function checkForShadows(scope: TSESLint.Scope.Scope): void { + // ignore global augmentation + if (isGlobalAugmentation(scope)) { + return; + } + const variables = scope.variables; for (const variable of variables) { diff --git a/packages/eslint-plugin/tests/rules/no-shadow.test.ts b/packages/eslint-plugin/tests/rules/no-shadow.test.ts index d7c81d83449..abc78ee5f3e 100644 --- a/packages/eslint-plugin/tests/rules/no-shadow.test.ts +++ b/packages/eslint-plugin/tests/rules/no-shadow.test.ts @@ -116,6 +116,49 @@ type Fn = (Foo: string) => typeof Foo; Foo: 'writable', }, }, + // https://github.com/typescript-eslint/typescript-eslint/issues/2724 + { + code: ` + declare global { + interface ArrayConstructor {} + } + export {}; + `, + options: [{ builtinGlobals: true }], + }, + ` + declare global { + const a: string; + + namespace Foo { + const a: number; + } + } + export {}; + `, + { + code: ` + declare global { + type A = 'foo'; + + namespace Foo { + type A = 'bar'; + } + } + export {}; + `, + options: [{ ignoreTypeValueShadow: false }], + }, + { + code: ` + declare global { + const foo: string; + type Fn = (foo: number) => void; + } + export {}; + `, + options: [{ ignoreFunctionTypeParameterNameValueShadow: false }], + }, ], invalid: [ {