Skip to content

Commit 7812f24

Browse files
Copilotjakebailey
andauthored
Fix TS2540 not reported for readonly properties accessed through imports (#2179)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
1 parent 320b8d9 commit 7812f24

File tree

10 files changed

+215
-307
lines changed

10 files changed

+215
-307
lines changed

internal/checker/checker.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26600,11 +26600,6 @@ func (c *Checker) isAssignmentToReadonlyEntity(expr *ast.Node, symbol *ast.Symbo
2660026600
if expressionSymbol.Flags&ast.SymbolFlagsModuleExports != 0 {
2660126601
return false
2660226602
}
26603-
// references through namespace import should be readonly
26604-
if expressionSymbol.Flags&ast.SymbolFlagsAlias != 0 {
26605-
declaration := c.getDeclarationOfAliasSymbol(expressionSymbol)
26606-
return declaration != nil && ast.IsNamespaceImport(declaration)
26607-
}
2660826603
}
2660926604
}
2661026605
if c.isReadonlySymbol(symbol) {
@@ -26627,6 +26622,17 @@ func (c *Checker) isAssignmentToReadonlyEntity(expr *ast.Node, symbol *ast.Symbo
2662726622
}
2662826623
return true
2662926624
}
26625+
if ast.IsAccessExpression(expr) {
26626+
// references through namespace import should be readonly
26627+
node := ast.SkipParentheses(expr.Expression())
26628+
if ast.IsIdentifier(node) {
26629+
expressionSymbol := c.getResolvedSymbol(node)
26630+
if expressionSymbol.Flags&ast.SymbolFlagsAlias != 0 {
26631+
declaration := c.getDeclarationOfAliasSymbol(expressionSymbol)
26632+
return declaration != nil && ast.IsNamespaceImport(declaration)
26633+
}
26634+
}
26635+
}
2663026636
return false
2663126637
}
2663226638

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
b.ts(3,5): error TS2540: Cannot assign to 'a' because it is a read-only property.
2+
3+
4+
==== a.ts (0 errors) ====
5+
const foo = {
6+
a: 1
7+
}
8+
9+
export default foo as Readonly<typeof foo>
10+
11+
==== b.ts (1 errors) ====
12+
import foo from './a'
13+
14+
foo.a = 2
15+
~
16+
!!! error TS2540: Cannot assign to 'a' because it is a read-only property.
17+
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//// [tests/cases/compiler/readonlyDefaultExport.ts] ////
2+
3+
//// [a.ts]
4+
const foo = {
5+
a: 1
6+
}
7+
8+
export default foo as Readonly<typeof foo>
9+
10+
//// [b.ts]
11+
import foo from './a'
12+
13+
foo.a = 2
14+
15+
16+
//// [a.js]
17+
"use strict";
18+
Object.defineProperty(exports, "__esModule", { value: true });
19+
const foo = {
20+
a: 1
21+
};
22+
exports.default = foo;
23+
//// [b.js]
24+
"use strict";
25+
var __importDefault = (this && this.__importDefault) || function (mod) {
26+
return (mod && mod.__esModule) ? mod : { "default": mod };
27+
};
28+
Object.defineProperty(exports, "__esModule", { value: true });
29+
const a_1 = __importDefault(require("./a"));
30+
a_1.default.a = 2;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//// [tests/cases/compiler/readonlyDefaultExport.ts] ////
2+
3+
=== a.ts ===
4+
const foo = {
5+
>foo : Symbol(foo, Decl(a.ts, 0, 5))
6+
7+
a: 1
8+
>a : Symbol(a, Decl(a.ts, 0, 13))
9+
}
10+
11+
export default foo as Readonly<typeof foo>
12+
>foo : Symbol(foo, Decl(a.ts, 0, 5))
13+
>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --))
14+
>foo : Symbol(foo, Decl(a.ts, 0, 5))
15+
16+
=== b.ts ===
17+
import foo from './a'
18+
>foo : Symbol(foo, Decl(b.ts, 0, 6))
19+
20+
foo.a = 2
21+
>foo.a : Symbol(a, Decl(a.ts, 0, 13))
22+
>foo : Symbol(foo, Decl(b.ts, 0, 6))
23+
>a : Symbol(a, Decl(a.ts, 0, 13))
24+
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//// [tests/cases/compiler/readonlyDefaultExport.ts] ////
2+
3+
=== a.ts ===
4+
const foo = {
5+
>foo : { a: number; }
6+
>{ a: 1} : { a: number; }
7+
8+
a: 1
9+
>a : number
10+
>1 : 1
11+
}
12+
13+
export default foo as Readonly<typeof foo>
14+
>foo as Readonly<typeof foo> : Readonly<{ a: number; }>
15+
>foo : { a: number; }
16+
>foo : { a: number; }
17+
18+
=== b.ts ===
19+
import foo from './a'
20+
>foo : Readonly<{ a: number; }>
21+
22+
foo.a = 2
23+
>foo.a = 2 : 2
24+
>foo.a : any
25+
>foo : Readonly<{ a: number; }>
26+
>a : any
27+
>2 : 2
28+

testdata/baselines/reference/submodule/compiler/constDeclarations-access5.errors.txt

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,84 @@
1-
constDeclarations_access_2.ts(4,1): error TS2322: Type '1' is not assignable to type '0'.
1+
constDeclarations_access_2.ts(4,3): error TS2540: Cannot assign to 'x' because it is a read-only property.
2+
constDeclarations_access_2.ts(5,3): error TS2540: Cannot assign to 'x' because it is a read-only property.
3+
constDeclarations_access_2.ts(6,3): error TS2540: Cannot assign to 'x' because it is a read-only property.
4+
constDeclarations_access_2.ts(7,3): error TS2540: Cannot assign to 'x' because it is a read-only property.
5+
constDeclarations_access_2.ts(8,3): error TS2540: Cannot assign to 'x' because it is a read-only property.
6+
constDeclarations_access_2.ts(9,3): error TS2540: Cannot assign to 'x' because it is a read-only property.
7+
constDeclarations_access_2.ts(10,3): error TS2540: Cannot assign to 'x' because it is a read-only property.
8+
constDeclarations_access_2.ts(11,3): error TS2540: Cannot assign to 'x' because it is a read-only property.
9+
constDeclarations_access_2.ts(12,3): error TS2540: Cannot assign to 'x' because it is a read-only property.
10+
constDeclarations_access_2.ts(13,3): error TS2540: Cannot assign to 'x' because it is a read-only property.
11+
constDeclarations_access_2.ts(14,3): error TS2540: Cannot assign to 'x' because it is a read-only property.
12+
constDeclarations_access_2.ts(15,3): error TS2540: Cannot assign to 'x' because it is a read-only property.
13+
constDeclarations_access_2.ts(17,3): error TS2540: Cannot assign to 'x' because it is a read-only property.
14+
constDeclarations_access_2.ts(18,3): error TS2540: Cannot assign to 'x' because it is a read-only property.
15+
constDeclarations_access_2.ts(19,5): error TS2540: Cannot assign to 'x' because it is a read-only property.
16+
constDeclarations_access_2.ts(20,5): error TS2540: Cannot assign to 'x' because it is a read-only property.
17+
constDeclarations_access_2.ts(22,7): error TS2540: Cannot assign to 'x' because it is a read-only property.
18+
constDeclarations_access_2.ts(24,3): error TS2540: Cannot assign to 'x' because it is a read-only property.
219

320

4-
==== constDeclarations_access_2.ts (1 errors) ====
21+
==== constDeclarations_access_2.ts (18 errors) ====
522
///<reference path='constDeclarations_access_1.ts'/>
623
import m = require('./constDeclarations_access_1');
724
// Errors
825
m.x = 1;
9-
~~~
10-
!!! error TS2322: Type '1' is not assignable to type '0'.
26+
~
27+
!!! error TS2540: Cannot assign to 'x' because it is a read-only property.
1128
m.x += 2;
29+
~
30+
!!! error TS2540: Cannot assign to 'x' because it is a read-only property.
1231
m.x -= 3;
32+
~
33+
!!! error TS2540: Cannot assign to 'x' because it is a read-only property.
1334
m.x *= 4;
35+
~
36+
!!! error TS2540: Cannot assign to 'x' because it is a read-only property.
1437
m.x /= 5;
38+
~
39+
!!! error TS2540: Cannot assign to 'x' because it is a read-only property.
1540
m.x %= 6;
41+
~
42+
!!! error TS2540: Cannot assign to 'x' because it is a read-only property.
1643
m.x <<= 7;
44+
~
45+
!!! error TS2540: Cannot assign to 'x' because it is a read-only property.
1746
m.x >>= 8;
47+
~
48+
!!! error TS2540: Cannot assign to 'x' because it is a read-only property.
1849
m.x >>>= 9;
50+
~
51+
!!! error TS2540: Cannot assign to 'x' because it is a read-only property.
1952
m.x &= 10;
53+
~
54+
!!! error TS2540: Cannot assign to 'x' because it is a read-only property.
2055
m.x |= 11;
56+
~
57+
!!! error TS2540: Cannot assign to 'x' because it is a read-only property.
2158
m.x ^= 12;
59+
~
60+
!!! error TS2540: Cannot assign to 'x' because it is a read-only property.
2261
m
2362
m.x++;
63+
~
64+
!!! error TS2540: Cannot assign to 'x' because it is a read-only property.
2465
m.x--;
66+
~
67+
!!! error TS2540: Cannot assign to 'x' because it is a read-only property.
2568
++m.x;
69+
~
70+
!!! error TS2540: Cannot assign to 'x' because it is a read-only property.
2671
--m.x;
72+
~
73+
!!! error TS2540: Cannot assign to 'x' because it is a read-only property.
2774

2875
++((m.x));
76+
~
77+
!!! error TS2540: Cannot assign to 'x' because it is a read-only property.
2978

3079
m["x"] = 0;
80+
~~~
81+
!!! error TS2540: Cannot assign to 'x' because it is a read-only property.
3182

3283
// OK
3384
var a = m.x + 1;

testdata/baselines/reference/submodule/compiler/constDeclarations-access5.errors.txt.diff

Lines changed: 0 additions & 93 deletions
This file was deleted.

0 commit comments

Comments
 (0)