diff --git a/internal/checker/checker.go b/internal/checker/checker.go index 4af7d0f220..6a2fac5cf7 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -26600,11 +26600,6 @@ func (c *Checker) isAssignmentToReadonlyEntity(expr *ast.Node, symbol *ast.Symbo if expressionSymbol.Flags&ast.SymbolFlagsModuleExports != 0 { return false } - // references through namespace import should be readonly - if expressionSymbol.Flags&ast.SymbolFlagsAlias != 0 { - declaration := c.getDeclarationOfAliasSymbol(expressionSymbol) - return declaration != nil && ast.IsNamespaceImport(declaration) - } } } if c.isReadonlySymbol(symbol) { @@ -26627,6 +26622,17 @@ func (c *Checker) isAssignmentToReadonlyEntity(expr *ast.Node, symbol *ast.Symbo } return true } + if ast.IsAccessExpression(expr) { + // references through namespace import should be readonly + node := ast.SkipParentheses(expr.Expression()) + if ast.IsIdentifier(node) { + expressionSymbol := c.getResolvedSymbol(node) + if expressionSymbol.Flags&ast.SymbolFlagsAlias != 0 { + declaration := c.getDeclarationOfAliasSymbol(expressionSymbol) + return declaration != nil && ast.IsNamespaceImport(declaration) + } + } + } return false } diff --git a/testdata/baselines/reference/compiler/readonlyDefaultExport.errors.txt b/testdata/baselines/reference/compiler/readonlyDefaultExport.errors.txt new file mode 100644 index 0000000000..50a31f44c8 --- /dev/null +++ b/testdata/baselines/reference/compiler/readonlyDefaultExport.errors.txt @@ -0,0 +1,17 @@ +b.ts(3,5): error TS2540: Cannot assign to 'a' because it is a read-only property. + + +==== a.ts (0 errors) ==== + const foo = { + a: 1 + } + + export default foo as Readonly + +==== b.ts (1 errors) ==== + import foo from './a' + + foo.a = 2 + ~ +!!! error TS2540: Cannot assign to 'a' because it is a read-only property. + \ No newline at end of file diff --git a/testdata/baselines/reference/compiler/readonlyDefaultExport.js b/testdata/baselines/reference/compiler/readonlyDefaultExport.js new file mode 100644 index 0000000000..c01a1152a5 --- /dev/null +++ b/testdata/baselines/reference/compiler/readonlyDefaultExport.js @@ -0,0 +1,30 @@ +//// [tests/cases/compiler/readonlyDefaultExport.ts] //// + +//// [a.ts] +const foo = { + a: 1 +} + +export default foo as Readonly + +//// [b.ts] +import foo from './a' + +foo.a = 2 + + +//// [a.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const foo = { + a: 1 +}; +exports.default = foo; +//// [b.js] +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const a_1 = __importDefault(require("./a")); +a_1.default.a = 2; diff --git a/testdata/baselines/reference/compiler/readonlyDefaultExport.symbols b/testdata/baselines/reference/compiler/readonlyDefaultExport.symbols new file mode 100644 index 0000000000..9e89f88f36 --- /dev/null +++ b/testdata/baselines/reference/compiler/readonlyDefaultExport.symbols @@ -0,0 +1,24 @@ +//// [tests/cases/compiler/readonlyDefaultExport.ts] //// + +=== a.ts === +const foo = { +>foo : Symbol(foo, Decl(a.ts, 0, 5)) + + a: 1 +>a : Symbol(a, Decl(a.ts, 0, 13)) +} + +export default foo as Readonly +>foo : Symbol(foo, Decl(a.ts, 0, 5)) +>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --)) +>foo : Symbol(foo, Decl(a.ts, 0, 5)) + +=== b.ts === +import foo from './a' +>foo : Symbol(foo, Decl(b.ts, 0, 6)) + +foo.a = 2 +>foo.a : Symbol(a, Decl(a.ts, 0, 13)) +>foo : Symbol(foo, Decl(b.ts, 0, 6)) +>a : Symbol(a, Decl(a.ts, 0, 13)) + diff --git a/testdata/baselines/reference/compiler/readonlyDefaultExport.types b/testdata/baselines/reference/compiler/readonlyDefaultExport.types new file mode 100644 index 0000000000..77abec3678 --- /dev/null +++ b/testdata/baselines/reference/compiler/readonlyDefaultExport.types @@ -0,0 +1,28 @@ +//// [tests/cases/compiler/readonlyDefaultExport.ts] //// + +=== a.ts === +const foo = { +>foo : { a: number; } +>{ a: 1} : { a: number; } + + a: 1 +>a : number +>1 : 1 +} + +export default foo as Readonly +>foo as Readonly : Readonly<{ a: number; }> +>foo : { a: number; } +>foo : { a: number; } + +=== b.ts === +import foo from './a' +>foo : Readonly<{ a: number; }> + +foo.a = 2 +>foo.a = 2 : 2 +>foo.a : any +>foo : Readonly<{ a: number; }> +>a : any +>2 : 2 + diff --git a/testdata/baselines/reference/submodule/compiler/constDeclarations-access5.errors.txt b/testdata/baselines/reference/submodule/compiler/constDeclarations-access5.errors.txt index 9900daf98b..b4cdcc1481 100644 --- a/testdata/baselines/reference/submodule/compiler/constDeclarations-access5.errors.txt +++ b/testdata/baselines/reference/submodule/compiler/constDeclarations-access5.errors.txt @@ -1,33 +1,84 @@ -constDeclarations_access_2.ts(4,1): error TS2322: Type '1' is not assignable to type '0'. +constDeclarations_access_2.ts(4,3): error TS2540: Cannot assign to 'x' because it is a read-only property. +constDeclarations_access_2.ts(5,3): error TS2540: Cannot assign to 'x' because it is a read-only property. +constDeclarations_access_2.ts(6,3): error TS2540: Cannot assign to 'x' because it is a read-only property. +constDeclarations_access_2.ts(7,3): error TS2540: Cannot assign to 'x' because it is a read-only property. +constDeclarations_access_2.ts(8,3): error TS2540: Cannot assign to 'x' because it is a read-only property. +constDeclarations_access_2.ts(9,3): error TS2540: Cannot assign to 'x' because it is a read-only property. +constDeclarations_access_2.ts(10,3): error TS2540: Cannot assign to 'x' because it is a read-only property. +constDeclarations_access_2.ts(11,3): error TS2540: Cannot assign to 'x' because it is a read-only property. +constDeclarations_access_2.ts(12,3): error TS2540: Cannot assign to 'x' because it is a read-only property. +constDeclarations_access_2.ts(13,3): error TS2540: Cannot assign to 'x' because it is a read-only property. +constDeclarations_access_2.ts(14,3): error TS2540: Cannot assign to 'x' because it is a read-only property. +constDeclarations_access_2.ts(15,3): error TS2540: Cannot assign to 'x' because it is a read-only property. +constDeclarations_access_2.ts(17,3): error TS2540: Cannot assign to 'x' because it is a read-only property. +constDeclarations_access_2.ts(18,3): error TS2540: Cannot assign to 'x' because it is a read-only property. +constDeclarations_access_2.ts(19,5): error TS2540: Cannot assign to 'x' because it is a read-only property. +constDeclarations_access_2.ts(20,5): error TS2540: Cannot assign to 'x' because it is a read-only property. +constDeclarations_access_2.ts(22,7): error TS2540: Cannot assign to 'x' because it is a read-only property. +constDeclarations_access_2.ts(24,3): error TS2540: Cannot assign to 'x' because it is a read-only property. -==== constDeclarations_access_2.ts (1 errors) ==== +==== constDeclarations_access_2.ts (18 errors) ==== /// import m = require('./constDeclarations_access_1'); // Errors m.x = 1; - ~~~ -!!! error TS2322: Type '1' is not assignable to type '0'. + ~ +!!! error TS2540: Cannot assign to 'x' because it is a read-only property. m.x += 2; + ~ +!!! error TS2540: Cannot assign to 'x' because it is a read-only property. m.x -= 3; + ~ +!!! error TS2540: Cannot assign to 'x' because it is a read-only property. m.x *= 4; + ~ +!!! error TS2540: Cannot assign to 'x' because it is a read-only property. m.x /= 5; + ~ +!!! error TS2540: Cannot assign to 'x' because it is a read-only property. m.x %= 6; + ~ +!!! error TS2540: Cannot assign to 'x' because it is a read-only property. m.x <<= 7; + ~ +!!! error TS2540: Cannot assign to 'x' because it is a read-only property. m.x >>= 8; + ~ +!!! error TS2540: Cannot assign to 'x' because it is a read-only property. m.x >>>= 9; + ~ +!!! error TS2540: Cannot assign to 'x' because it is a read-only property. m.x &= 10; + ~ +!!! error TS2540: Cannot assign to 'x' because it is a read-only property. m.x |= 11; + ~ +!!! error TS2540: Cannot assign to 'x' because it is a read-only property. m.x ^= 12; + ~ +!!! error TS2540: Cannot assign to 'x' because it is a read-only property. m m.x++; + ~ +!!! error TS2540: Cannot assign to 'x' because it is a read-only property. m.x--; + ~ +!!! error TS2540: Cannot assign to 'x' because it is a read-only property. ++m.x; + ~ +!!! error TS2540: Cannot assign to 'x' because it is a read-only property. --m.x; + ~ +!!! error TS2540: Cannot assign to 'x' because it is a read-only property. ++((m.x)); + ~ +!!! error TS2540: Cannot assign to 'x' because it is a read-only property. m["x"] = 0; + ~~~ +!!! error TS2540: Cannot assign to 'x' because it is a read-only property. // OK var a = m.x + 1; diff --git a/testdata/baselines/reference/submodule/compiler/constDeclarations-access5.errors.txt.diff b/testdata/baselines/reference/submodule/compiler/constDeclarations-access5.errors.txt.diff deleted file mode 100644 index 9d1bfa7cd5..0000000000 --- a/testdata/baselines/reference/submodule/compiler/constDeclarations-access5.errors.txt.diff +++ /dev/null @@ -1,93 +0,0 @@ ---- old.constDeclarations-access5.errors.txt -+++ new.constDeclarations-access5.errors.txt -@@= skipped -0, +0 lines =@@ --constDeclarations_access_2.ts(4,3): error TS2540: Cannot assign to 'x' because it is a read-only property. --constDeclarations_access_2.ts(5,3): error TS2540: Cannot assign to 'x' because it is a read-only property. --constDeclarations_access_2.ts(6,3): error TS2540: Cannot assign to 'x' because it is a read-only property. --constDeclarations_access_2.ts(7,3): error TS2540: Cannot assign to 'x' because it is a read-only property. --constDeclarations_access_2.ts(8,3): error TS2540: Cannot assign to 'x' because it is a read-only property. --constDeclarations_access_2.ts(9,3): error TS2540: Cannot assign to 'x' because it is a read-only property. --constDeclarations_access_2.ts(10,3): error TS2540: Cannot assign to 'x' because it is a read-only property. --constDeclarations_access_2.ts(11,3): error TS2540: Cannot assign to 'x' because it is a read-only property. --constDeclarations_access_2.ts(12,3): error TS2540: Cannot assign to 'x' because it is a read-only property. --constDeclarations_access_2.ts(13,3): error TS2540: Cannot assign to 'x' because it is a read-only property. --constDeclarations_access_2.ts(14,3): error TS2540: Cannot assign to 'x' because it is a read-only property. --constDeclarations_access_2.ts(15,3): error TS2540: Cannot assign to 'x' because it is a read-only property. --constDeclarations_access_2.ts(17,3): error TS2540: Cannot assign to 'x' because it is a read-only property. --constDeclarations_access_2.ts(18,3): error TS2540: Cannot assign to 'x' because it is a read-only property. --constDeclarations_access_2.ts(19,5): error TS2540: Cannot assign to 'x' because it is a read-only property. --constDeclarations_access_2.ts(20,5): error TS2540: Cannot assign to 'x' because it is a read-only property. --constDeclarations_access_2.ts(22,7): error TS2540: Cannot assign to 'x' because it is a read-only property. --constDeclarations_access_2.ts(24,3): error TS2540: Cannot assign to 'x' because it is a read-only property. -- -- --==== constDeclarations_access_2.ts (18 errors) ==== -+constDeclarations_access_2.ts(4,1): error TS2322: Type '1' is not assignable to type '0'. -+ -+ -+==== constDeclarations_access_2.ts (1 errors) ==== - /// - import m = require('./constDeclarations_access_1'); - // Errors - m.x = 1; -- ~ --!!! error TS2540: Cannot assign to 'x' because it is a read-only property. -+ ~~~ -+!!! error TS2322: Type '1' is not assignable to type '0'. - m.x += 2; -- ~ --!!! error TS2540: Cannot assign to 'x' because it is a read-only property. - m.x -= 3; -- ~ --!!! error TS2540: Cannot assign to 'x' because it is a read-only property. - m.x *= 4; -- ~ --!!! error TS2540: Cannot assign to 'x' because it is a read-only property. - m.x /= 5; -- ~ --!!! error TS2540: Cannot assign to 'x' because it is a read-only property. - m.x %= 6; -- ~ --!!! error TS2540: Cannot assign to 'x' because it is a read-only property. - m.x <<= 7; -- ~ --!!! error TS2540: Cannot assign to 'x' because it is a read-only property. - m.x >>= 8; -- ~ --!!! error TS2540: Cannot assign to 'x' because it is a read-only property. - m.x >>>= 9; -- ~ --!!! error TS2540: Cannot assign to 'x' because it is a read-only property. - m.x &= 10; -- ~ --!!! error TS2540: Cannot assign to 'x' because it is a read-only property. - m.x |= 11; -- ~ --!!! error TS2540: Cannot assign to 'x' because it is a read-only property. - m.x ^= 12; -- ~ --!!! error TS2540: Cannot assign to 'x' because it is a read-only property. - m - m.x++; -- ~ --!!! error TS2540: Cannot assign to 'x' because it is a read-only property. - m.x--; -- ~ --!!! error TS2540: Cannot assign to 'x' because it is a read-only property. - ++m.x; -- ~ --!!! error TS2540: Cannot assign to 'x' because it is a read-only property. - --m.x; -- ~ --!!! error TS2540: Cannot assign to 'x' because it is a read-only property. - - ++((m.x)); -- ~ --!!! error TS2540: Cannot assign to 'x' because it is a read-only property. - - m["x"] = 0; -- ~~~ --!!! error TS2540: Cannot assign to 'x' because it is a read-only property. - - // OK - var a = m.x + 1; \ No newline at end of file diff --git a/testdata/baselines/reference/submodule/compiler/constDeclarations-access5.types b/testdata/baselines/reference/submodule/compiler/constDeclarations-access5.types index 822381ead2..d737b7bed9 100644 --- a/testdata/baselines/reference/submodule/compiler/constDeclarations-access5.types +++ b/testdata/baselines/reference/submodule/compiler/constDeclarations-access5.types @@ -8,86 +8,86 @@ import m = require('./constDeclarations_access_1'); // Errors m.x = 1; >m.x = 1 : 1 ->m.x : 0 +>m.x : any >m : typeof m ->x : 0 +>x : any >1 : 1 m.x += 2; ->m.x += 2 : number ->m.x : number +>m.x += 2 : any +>m.x : any >m : typeof m ->x : number +>x : any >2 : 2 m.x -= 3; >m.x -= 3 : number ->m.x : number +>m.x : any >m : typeof m ->x : number +>x : any >3 : 3 m.x *= 4; >m.x *= 4 : number ->m.x : number +>m.x : any >m : typeof m ->x : number +>x : any >4 : 4 m.x /= 5; >m.x /= 5 : number ->m.x : number +>m.x : any >m : typeof m ->x : number +>x : any >5 : 5 m.x %= 6; >m.x %= 6 : number ->m.x : number +>m.x : any >m : typeof m ->x : number +>x : any >6 : 6 m.x <<= 7; >m.x <<= 7 : number ->m.x : number +>m.x : any >m : typeof m ->x : number +>x : any >7 : 7 m.x >>= 8; >m.x >>= 8 : number ->m.x : number +>m.x : any >m : typeof m ->x : number +>x : any >8 : 8 m.x >>>= 9; >m.x >>>= 9 : number ->m.x : number +>m.x : any >m : typeof m ->x : number +>x : any >9 : 9 m.x &= 10; >m.x &= 10 : number ->m.x : number +>m.x : any >m : typeof m ->x : number +>x : any >10 : 10 m.x |= 11; >m.x |= 11 : number ->m.x : number +>m.x : any >m : typeof m ->x : number +>x : any >11 : 11 m.x ^= 12; >m.x ^= 12 : number ->m.x : number +>m.x : any >m : typeof m ->x : number +>x : any >12 : 12 m @@ -95,39 +95,39 @@ m m.x++; >m.x++ : number ->m.x : number +>m.x : any >m : typeof m ->x : number +>x : any m.x--; >m.x-- : number ->m.x : number +>m.x : any >m : typeof m ->x : number +>x : any ++m.x; >++m.x : number ->m.x : number +>m.x : any >m : typeof m ->x : number +>x : any --m.x; >--m.x : number ->m.x : number +>m.x : any >m : typeof m ->x : number +>x : any ++((m.x)); >++((m.x)) : number ->((m.x)) : number ->(m.x) : number ->m.x : number +>((m.x)) : any +>(m.x) : any +>m.x : any >m : typeof m ->x : number +>x : any m["x"] = 0; >m["x"] = 0 : 0 ->m["x"] : 0 +>m["x"] : any >m : typeof m >"x" : "x" >0 : 0 diff --git a/testdata/baselines/reference/submodule/compiler/constDeclarations-access5.types.diff b/testdata/baselines/reference/submodule/compiler/constDeclarations-access5.types.diff deleted file mode 100644 index e14da40efa..0000000000 --- a/testdata/baselines/reference/submodule/compiler/constDeclarations-access5.types.diff +++ /dev/null @@ -1,167 +0,0 @@ ---- old.constDeclarations-access5.types -+++ new.constDeclarations-access5.types -@@= skipped -7, +7 lines =@@ - // Errors - m.x = 1; - >m.x = 1 : 1 -->m.x : any -+>m.x : 0 - >m : typeof m -->x : any -+>x : 0 - >1 : 1 - - m.x += 2; -->m.x += 2 : any -->m.x : any -+>m.x += 2 : number -+>m.x : number - >m : typeof m -->x : any -+>x : number - >2 : 2 - - m.x -= 3; - >m.x -= 3 : number -->m.x : any -+>m.x : number - >m : typeof m -->x : any -+>x : number - >3 : 3 - - m.x *= 4; - >m.x *= 4 : number -->m.x : any -+>m.x : number - >m : typeof m -->x : any -+>x : number - >4 : 4 - - m.x /= 5; - >m.x /= 5 : number -->m.x : any -+>m.x : number - >m : typeof m -->x : any -+>x : number - >5 : 5 - - m.x %= 6; - >m.x %= 6 : number -->m.x : any -+>m.x : number - >m : typeof m -->x : any -+>x : number - >6 : 6 - - m.x <<= 7; - >m.x <<= 7 : number -->m.x : any -+>m.x : number - >m : typeof m -->x : any -+>x : number - >7 : 7 - - m.x >>= 8; - >m.x >>= 8 : number -->m.x : any -+>m.x : number - >m : typeof m -->x : any -+>x : number - >8 : 8 - - m.x >>>= 9; - >m.x >>>= 9 : number -->m.x : any -+>m.x : number - >m : typeof m -->x : any -+>x : number - >9 : 9 - - m.x &= 10; - >m.x &= 10 : number -->m.x : any -+>m.x : number - >m : typeof m -->x : any -+>x : number - >10 : 10 - - m.x |= 11; - >m.x |= 11 : number -->m.x : any -+>m.x : number - >m : typeof m -->x : any -+>x : number - >11 : 11 - - m.x ^= 12; - >m.x ^= 12 : number -->m.x : any -+>m.x : number - >m : typeof m -->x : any -+>x : number - >12 : 12 - - m -@@= skipped -87, +87 lines =@@ - - m.x++; - >m.x++ : number -->m.x : any -+>m.x : number - >m : typeof m -->x : any -+>x : number - - m.x--; - >m.x-- : number -->m.x : any -+>m.x : number - >m : typeof m -->x : any -+>x : number - - ++m.x; - >++m.x : number -->m.x : any -+>m.x : number - >m : typeof m -->x : any -+>x : number - - --m.x; - >--m.x : number -->m.x : any -+>m.x : number - >m : typeof m -->x : any -+>x : number - - ++((m.x)); - >++((m.x)) : number -->((m.x)) : any -->(m.x) : any -->m.x : any -+>((m.x)) : number -+>(m.x) : number -+>m.x : number - >m : typeof m -->x : any -+>x : number - - m["x"] = 0; - >m["x"] = 0 : 0 -->m["x"] : any -+>m["x"] : 0 - >m : typeof m - >"x" : "x" - >0 : 0 \ No newline at end of file diff --git a/testdata/tests/cases/compiler/readonlyDefaultExport.ts b/testdata/tests/cases/compiler/readonlyDefaultExport.ts new file mode 100644 index 0000000000..907824c899 --- /dev/null +++ b/testdata/tests/cases/compiler/readonlyDefaultExport.ts @@ -0,0 +1,12 @@ +// @module: commonjs +// @Filename: a.ts +const foo = { + a: 1 +} + +export default foo as Readonly + +// @Filename: b.ts +import foo from './a' + +foo.a = 2