From e4babd40e00f572c3f308e47c8d98e2d7df550a4 Mon Sep 17 00:00:00 2001 From: Eli Barzilay Date: Fri, 27 Mar 2020 15:54:34 -0400 Subject: [PATCH] Skip `isBlockScopedNameDeclaredBeforeUse` error in interface or type declarations Fixes #35947. --- src/compiler/checker.ts | 6 +++- .../reference/forwardRefInTypeDeclaration.js | 18 ++++++++++++ .../forwardRefInTypeDeclaration.symbols | 27 +++++++++++++++++ .../forwardRefInTypeDeclaration.types | 29 +++++++++++++++++++ .../compiler/forwardRefInTypeDeclaration.ts | 11 +++++++ 5 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/forwardRefInTypeDeclaration.js create mode 100644 tests/baselines/reference/forwardRefInTypeDeclaration.symbols create mode 100644 tests/baselines/reference/forwardRefInTypeDeclaration.types create mode 100644 tests/cases/compiler/forwardRefInTypeDeclaration.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ac38c26d62e..6ebcbdc2227 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1418,7 +1418,7 @@ namespace ts { return true; } - if (!!(usage.flags & NodeFlags.JSDoc) || isInTypeQuery(usage)) { + if (!!(usage.flags & NodeFlags.JSDoc) || isInTypeQuery(usage) || usageInTypeDeclaration()) { return true; } if (isUsedInFunctionOrInstanceProperty(usage, declaration)) { @@ -1432,6 +1432,10 @@ namespace ts { } return false; + function usageInTypeDeclaration() { + return !!findAncestor(usage, node => isInterfaceDeclaration(node) || isTypeAliasDeclaration(node)); + } + function isImmediatelyUsedInInitializerOfBlockScopedVariable(declaration: VariableDeclaration, usage: Node): boolean { switch (declaration.parent.parent.kind) { case SyntaxKind.VariableStatement: diff --git a/tests/baselines/reference/forwardRefInTypeDeclaration.js b/tests/baselines/reference/forwardRefInTypeDeclaration.js new file mode 100644 index 00000000000..ee2dda355f6 --- /dev/null +++ b/tests/baselines/reference/forwardRefInTypeDeclaration.js @@ -0,0 +1,18 @@ +//// [forwardRefInTypeDeclaration.ts] +// forward ref ignored in a typeof +declare let s: typeof s1; +const s1 = "x"; + +// ignored anywhere in an interface (#35947) +interface Foo2 { [s2]: number; } +const s2 = "x"; + +// or in a type definition +type Foo3 = { [s3]: number; } +const s3 = "x"; + + +//// [forwardRefInTypeDeclaration.js] +var s1 = "x"; +var s2 = "x"; +var s3 = "x"; diff --git a/tests/baselines/reference/forwardRefInTypeDeclaration.symbols b/tests/baselines/reference/forwardRefInTypeDeclaration.symbols new file mode 100644 index 00000000000..f8ad803779c --- /dev/null +++ b/tests/baselines/reference/forwardRefInTypeDeclaration.symbols @@ -0,0 +1,27 @@ +=== tests/cases/compiler/forwardRefInTypeDeclaration.ts === +// forward ref ignored in a typeof +declare let s: typeof s1; +>s : Symbol(s, Decl(forwardRefInTypeDeclaration.ts, 1, 11)) +>s1 : Symbol(s1, Decl(forwardRefInTypeDeclaration.ts, 2, 5)) + +const s1 = "x"; +>s1 : Symbol(s1, Decl(forwardRefInTypeDeclaration.ts, 2, 5)) + +// ignored anywhere in an interface (#35947) +interface Foo2 { [s2]: number; } +>Foo2 : Symbol(Foo2, Decl(forwardRefInTypeDeclaration.ts, 2, 15)) +>[s2] : Symbol(Foo2[s2], Decl(forwardRefInTypeDeclaration.ts, 5, 16)) +>s2 : Symbol(s2, Decl(forwardRefInTypeDeclaration.ts, 6, 5)) + +const s2 = "x"; +>s2 : Symbol(s2, Decl(forwardRefInTypeDeclaration.ts, 6, 5)) + +// or in a type definition +type Foo3 = { [s3]: number; } +>Foo3 : Symbol(Foo3, Decl(forwardRefInTypeDeclaration.ts, 6, 15)) +>[s3] : Symbol([s3], Decl(forwardRefInTypeDeclaration.ts, 9, 13)) +>s3 : Symbol(s3, Decl(forwardRefInTypeDeclaration.ts, 10, 5)) + +const s3 = "x"; +>s3 : Symbol(s3, Decl(forwardRefInTypeDeclaration.ts, 10, 5)) + diff --git a/tests/baselines/reference/forwardRefInTypeDeclaration.types b/tests/baselines/reference/forwardRefInTypeDeclaration.types new file mode 100644 index 00000000000..de487ec372c --- /dev/null +++ b/tests/baselines/reference/forwardRefInTypeDeclaration.types @@ -0,0 +1,29 @@ +=== tests/cases/compiler/forwardRefInTypeDeclaration.ts === +// forward ref ignored in a typeof +declare let s: typeof s1; +>s : "x" +>s1 : "x" + +const s1 = "x"; +>s1 : "x" +>"x" : "x" + +// ignored anywhere in an interface (#35947) +interface Foo2 { [s2]: number; } +>[s2] : number +>s2 : "x" + +const s2 = "x"; +>s2 : "x" +>"x" : "x" + +// or in a type definition +type Foo3 = { [s3]: number; } +>Foo3 : Foo3 +>[s3] : number +>s3 : "x" + +const s3 = "x"; +>s3 : "x" +>"x" : "x" + diff --git a/tests/cases/compiler/forwardRefInTypeDeclaration.ts b/tests/cases/compiler/forwardRefInTypeDeclaration.ts new file mode 100644 index 00000000000..ef29f727862 --- /dev/null +++ b/tests/cases/compiler/forwardRefInTypeDeclaration.ts @@ -0,0 +1,11 @@ +// forward ref ignored in a typeof +declare let s: typeof s1; +const s1 = "x"; + +// ignored anywhere in an interface (#35947) +interface Foo2 { [s2]: number; } +const s2 = "x"; + +// or in a type definition +type Foo3 = { [s3]: number; } +const s3 = "x";