diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index d392785d4181f..c4f09876bb20e 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -14687,10 +14687,14 @@ func (c *Checker) getLateBoundSymbol(symbol *ast.Symbol) *ast.Symbol { if links.lateSymbol == nil && core.Some(symbol.Declarations(), c.hasLateBindableName) { // force late binding of members/exports. This will set the late-bound symbol parent := c.getMergedSymbol(symbol.Parent()) - if core.Some(symbol.Declarations(), ast.HasStaticModifier) { - c.getExportsOfSymbol(parent) - } else { - c.getMembersOfSymbol(parent) + // Parent can be nil for top-level script expandos (SourceFile has no symbol) when + // checking was skipped (--noCheck) and late binding has not run yet. + if parent != nil { + if core.Some(symbol.Declarations(), ast.HasStaticModifier) { + c.getExportsOfSymbol(parent) + } else { + c.getMembersOfSymbol(parent) + } } } if links.lateSymbol == nil { diff --git a/tsc/testdata/baselines/reference/compiler/noCheckExpandoElementAccessAssignment.js b/tsc/testdata/baselines/reference/compiler/noCheckExpandoElementAccessAssignment.js new file mode 100644 index 0000000000000..0b1f387e18dfc --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/noCheckExpandoElementAccessAssignment.js @@ -0,0 +1,16 @@ +//// [tests/cases/compiler/noCheckExpandoElementAccessAssignment.ts] //// + +//// [noCheckExpandoElementAccessAssignment.ts] +const k = "bar"; +foo[k] = 1; +function foo() {} + + + + +//// [noCheckExpandoElementAccessAssignment.d.ts] +declare const k = "bar"; +declare function foo(): void; +declare namespace foo { + var bar: number; +} diff --git a/tsc/testdata/baselines/reference/compiler/noCheckExpandoElementAccessAssignment.symbols b/tsc/testdata/baselines/reference/compiler/noCheckExpandoElementAccessAssignment.symbols new file mode 100644 index 0000000000000..6915aec55afa0 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/noCheckExpandoElementAccessAssignment.symbols @@ -0,0 +1,13 @@ +//// [tests/cases/compiler/noCheckExpandoElementAccessAssignment.ts] //// + +=== noCheckExpandoElementAccessAssignment.ts === +const k = "bar"; +>k : Symbol(k, Decl(noCheckExpandoElementAccessAssignment.ts, 0, 5)) + +foo[k] = 1; +>foo : Symbol(foo, Decl(noCheckExpandoElementAccessAssignment.ts, 1, 11)) +>k : Symbol(k, Decl(noCheckExpandoElementAccessAssignment.ts, 0, 5)) + +function foo() {} +>foo : Symbol(foo, Decl(noCheckExpandoElementAccessAssignment.ts, 1, 11)) + diff --git a/tsc/testdata/baselines/reference/compiler/noCheckExpandoElementAccessAssignment.types b/tsc/testdata/baselines/reference/compiler/noCheckExpandoElementAccessAssignment.types new file mode 100644 index 0000000000000..4dbd3c67ddde0 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/noCheckExpandoElementAccessAssignment.types @@ -0,0 +1,17 @@ +//// [tests/cases/compiler/noCheckExpandoElementAccessAssignment.ts] //// + +=== noCheckExpandoElementAccessAssignment.ts === +const k = "bar"; +>k : "bar" +>"bar" : "bar" + +foo[k] = 1; +>foo[k] = 1 : 1 +>foo[k] : number +>foo : { (): void; bar: number; } +>k : "bar" +>1 : 1 + +function foo() {} +>foo : { (): void; bar: number; } + diff --git a/tsc/testdata/tests/cases/compiler/noCheckExpandoElementAccessAssignment.ts b/tsc/testdata/tests/cases/compiler/noCheckExpandoElementAccessAssignment.ts new file mode 100644 index 0000000000000..5cf68fc81395b --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/noCheckExpandoElementAccessAssignment.ts @@ -0,0 +1,8 @@ +// @target: es2015 +// @noCheck: true +// @emitDeclarationOnly: true +// @declaration: true + +const k = "bar"; +foo[k] = 1; +function foo() {}