8000 fix(eslint-plugin): [no-unused-vars] better handling for declared mod… · raszi/typescript-eslint@02d72d4 · GitHub
[go: up one dir, main page]

Skip to content

Commit 02d72d4

Browse files
authored
fix(eslint-plugin): [no-unused-vars] better handling for declared modules (typescript-eslint#2553)
Fixes typescript-eslint#2523 - `declare global` should never be marked as unused. - namespaces within declared namespaces all ambiently export their children
1 parent bf88c84 commit 02d72d4

File tree

2 files changed

+97
-3
lines changed

2 files changed

+97
-3
lines changed

packages/eslint-plugin/src/rules/no-unused-vars.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,19 @@ export default util.createRule<Options, MessageIds>({
219219
markDeclarationChildAsUsed(node);
220220
},
221221

222+
// global augmentation can be in any file, and they do not need exports
223+
'TSModuleDeclaration[declare = true][global = true]'(): void {
224+
context.markVariableAsUsed('global');
225+
},
226+
227+
// children of a namespace that is a child of a declared namespace are auto-exported
228+
[ambientDeclarationSelector(
229+
'TSModuleDeclaration[declare = true] > TSModuleBlock TSModuleDeclaration > TSModuleBlock',
230+
false,
231+
)](node: DeclarationSelectorNode): void {
232+
markDeclarationChildAsUsed(node);
233+
},
234+
222235
// declared namespace handling
223236
[ambientDeclarationSelector(
224237
'TSModuleDeclaration[declare = true] > TSModuleBlock',
@@ -229,9 +242,12 @@ export default util.createRule<Options, MessageIds>({
229242
util.NullThrowsReasons.MissingParent,
230243
) as TSESTree.TSModuleDeclaration;
231244

232-
// declared modules with an `export =` statement will only export that one thing
245+
// declared ambient modules with an `export =` statement will only export that one thing
233246
// all other statements are not automatically exported in this case
234-
if (checkModuleDeclForExportEquals(moduleDecl)) {
247+
if (
248+
moduleDecl.id.type === AST_NODE_TYPES.Literal &&
249+
checkModuleDeclForExportEquals(moduleDecl)
250+
) {
235251
return;
236252
}
237253

@@ -284,7 +300,7 @@ export default util.createRule<Options, MessageIds>({
284300
AST_NODE_TYPES.TSEnumDeclaration,
285301
AST_NODE_TYPES.TSModuleDeclaration,
286302
AST_NODE_TYPES.VariableDeclaration,
287-
].join(', ')})${childDeclare ? '[declare=true]' : ''}`,
303+
].join(', ')})${childDeclare ? '[declare = true]' : ''}`,
288304
].join(', ');
289305
}
290306
function markDeclarationChildAsUsed(node: DeclarationSelectorNode): void {

packages/eslint-plugin/tests/rules/no-unused-vars.test.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,32 @@ declare module 'foo' {
858858
type Test = 1;
859859
const x: Test = 1;
860860
export = x;
861+
}
862+
`,
863+
// https://github.com/typescript-eslint/typescript-eslint/issues/2523
864+
`
865+
declare global {
866+
interface Foo {}
867+
}
868+
`,
869+
`
870+
declare global {
871+
namespace jest {
872+
interface Matchers<R> {
873+
toBeSeven: () => R;
874+
}
875+
}
876+
}
877+
`,
878+
`
879+
export declare namespace Foo {
880+
namespace Bar {
881+
namespace Baz {
882+
namespace Bam {
883+
const x = 1;
884+
}
885+
}
886+
}
861887
}
862888
`,
863889
],
@@ -1456,5 +1482,57 @@ declare module 'foo' {
14561482
},
14571483
],
14581484
},
1485+
{
1486+
code: `
1487+
// not declared
1488+
export namespace Foo {
1489+
namespace Bar {
1490+
namespace Baz {
1491+
namespace Bam {
1492+
const x = 1;
1493+
}
1494+
}
1495+
}
1496+
}
1497+
`,
1498+
errors: [
1499+
{
1500+
messageId: 'unusedVar',
1501+
line: 4,
1502+
data: {
1503+
varName: 'Bar',
1504+
action: 'defined',
1505+
additional: '',
1506+
},
1507+
},
1508+
{
1509+
messageId: 'unusedVar',
1510+
line: 5,
1511+
data: {
1512+
varName: 'Baz',
1513+
action: 'defined',
1514+
additional: '',
1515+
},
1516+
},
1517+
{
1518+
messageId: 'unusedVar',
1519+
line: 6,
1520+
data: {
1521+
varName: 'Bam',
1522+
action: 'defined',
1523+
additional: '',
1524+
},
1525+
},
1526+
{
1527+
messageId: 'unusedVar',
1528+
line: 7,
1529+
data: {
1530+
varName: 'x',
1531+
action: 'assigned a value',
1532+
additional: '',
1533+
},
1534+
},
1535+
],
1536+
},
14591537
],
14601538
});

0 commit comments

Comments
 (0)
0