diff --git a/packages/eslint-plugin/tests/rules/no-shadow.test.ts b/packages/eslint-plugin/tests/rules/no-shadow.test.ts index bbaad211a25..d7c81d83449 100644 --- a/packages/eslint-plugin/tests/rules/no-shadow.test.ts +++ b/packages/eslint-plugin/tests/rules/no-shadow.test.ts @@ -11,6 +11,14 @@ const ruleTester = new RuleTester({ ruleTester.run('no-shadow TS tests', rule, { valid: [ + // nested conditional types + ` +export type ArrayInput = Func extends (arg0: Array) => any + ? T[] + : Func extends (...args: infer T) => any + ? T + : never; + `, ` function foo() { var Object = 0; diff --git a/packages/scope-manager/src/referencer/TypeVisitor.ts b/packages/scope-manager/src/referencer/TypeVisitor.ts index 5e43f83bb32..75b5f614e32 100644 --- a/packages/scope-manager/src/referencer/TypeVisitor.ts +++ b/packages/scope-manager/src/referencer/TypeVisitor.ts @@ -94,9 +94,12 @@ class TypeVisitor extends Visitor { // which are only accessible from inside the conditional parameter this.#referencer.scopeManager.nestConditionalTypeScope(node); - this.visitChildren(node); + // type parameters inferred in the condition clause are not accessible within the false branch + this.visitChildren(node, ['falseType']); this.#referencer.close(node); + + this.visit(node.falseType); } protected TSConstructorType(node: TSESTree.TSConstructorType): void { diff --git a/packages/scope-manager/tests/fixtures/type-declaration/conditional-nested.ts b/packages/scope-manager/tests/fixtures/type-declaration/conditional-nested.ts new file mode 100644 index 00000000000..ba4335437e6 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/conditional-nested.ts @@ -0,0 +1,5 @@ +type Test = T extends Array + ? U + : T extends Set + ? U + : never; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/conditional-nested.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/conditional-nested.ts.shot new file mode 100644 index 00000000000..21cdfcca5f3 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/conditional-nested.ts.shot @@ -0,0 +1,170 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration conditional-nested 1`] = ` +ScopeManager { + variables: Array [ + ImplicitGlobalConstTypeVariable, + Variable$2 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"Test">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "Test", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeParameter$2, + }, + ], + name: "T", + references: Array [ + Reference$1 { + identifier: Identifier<"T">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: Variable$3, + }, + Reference$4 { + identifier: Identifier<"T">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: Variable$3, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"U">, + node: TSTypeParameter$3, + }, + ], + name: "U", + references: Array [ + Reference$3 { + identifier: Identifier<"U">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: Variable$4, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$5 { + defs: Array [ + TypeDefinition$4 { + name: Identifier<"U">, + node: TSTypeParameter$4, + }, + ], + name: "U", + references: Array [ + Reference$6 { + identifier: Identifier<"U">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: Variable$5, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$5, + isStrict: false, + references: Array [], + set: Map { + "const" => ImplicitGlobalConstTypeVariable, + "Test" => Variable$2, + }, + type: "global", + upper: null, + variables: Array [ + ImplicitGlobalConstTypeVariable, + Variable$2, + ], + }, + TypeScope$2 { + block: TSTypeAliasDeclaration$1, + isStrict: true, + references: Array [], + set: Map { + "T" => Variable$3, + }, + type: "type", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + ], + }, + ConditionalTypeScope$3 { + block: TSConditionalType$6, + isStrict: true, + references: Array [ + Reference$1, + Reference$2 { + identifier: Identifier<"Array">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: null, + }, + Reference$3, + ], + set: Map { + "U" => Variable$4, + }, + type: "conditionalType", + upper: TypeScope$2, + variables: Array [ + Variable$4, + ], + }, + ConditionalTypeScope$4 { + block: TSConditionalType$7, + isStrict: true, + references: Array [ + Reference$4, + Reference$5 { + identifier: Identifier<"Set">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: null, + }, + Reference$6, + ], + set: Map { + "U" => Variable$5, + }, + type: "conditionalType", + upper: TypeScope$2, + variables: Array [ + Variable$5, + ], + }, + ], +} +`;