Skip to content

Commit 96706a7

Browse files
authored
Merge pull request microsoft#29510 from Microsoft/constContexts
Const contexts for literal expressions
2 parents eb513a2 + 08fe06f commit 96706a7

File tree

10 files changed

+1015
-47
lines changed

10 files changed

+1015
-47
lines changed

src/compiler/checker.ts

Lines changed: 81 additions & 47 deletions
Large diffs are not rendered by default.

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,6 +1027,10 @@
10271027
"category": "Error",
10281028
"code": 1354
10291029
},
1030+
"A 'const' assertion can only be applied to a string, number, boolean, array, or object literal.": {
1031+
"category": "Error",
1032+
"code": 1355
1033+
},
10301034

10311035
"Duplicate identifier '{0}'.": {
10321036
"category": "Error",

src/compiler/utilities.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5607,6 +5607,11 @@ namespace ts {
56075607
return node.kind === SyntaxKind.TypeAssertionExpression;
56085608
}
56095609

5610+
export function isConstTypeReference(node: Node) {
5611+
return isTypeReferenceNode(node) && isIdentifier(node.typeName) &&
5612+
node.typeName.escapedText === "const" && !node.typeArguments;
5613+
}
5614+
56105615
export function isParenthesizedExpression(node: Node): node is ParenthesizedExpression {
56115616
return node.kind === SyntaxKind.ParenthesizedExpression;
56125617
}

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3360,6 +3360,7 @@ declare namespace ts {
33603360
function isNewExpression(node: Node): node is NewExpression;
33613361
function isTaggedTemplateExpression(node: Node): node is TaggedTemplateExpression;
33623362
function isTypeAssertion(node: Node): node is TypeAssertion;
3363+
function isConstTypeReference(node: Node): boolean;
33633364
function isParenthesizedExpression(node: Node): node is ParenthesizedExpression;
33643365
function skipPartiallyEmittedExpressions(node: Expression): Expression;
33653366
function skipPartiallyEmittedExpressions(node: Node): Node;

tests/baselines/reference/api/typescript.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3360,6 +3360,7 @@ declare namespace ts {
33603360
function isNewExpression(node: Node): node is NewExpression;
33613361
function isTaggedTemplateExpression(node: Node): node is TaggedTemplateExpression;
33623362
function isTypeAssertion(node: Node): node is TypeAssertion;
3363+
function isConstTypeReference(node: Node): boolean;
33633364
function isParenthesizedExpression(node: Node): node is ParenthesizedExpression;
33643365
function skipPartiallyEmittedExpressions(node: Expression): Expression;
33653366
function skipPartiallyEmittedExpressions(node: Node): Node;
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
tests/cases/conformance/expressions/typeAssertions/constAssertions.ts(44,32): error TS2540: Cannot assign to 'x' because it is a read-only property.
2+
tests/cases/conformance/expressions/typeAssertions/constAssertions.ts(61,10): error TS1355: A 'const' assertion can only be applied to a string, number, boolean, array, or object literal.
3+
tests/cases/conformance/expressions/typeAssertions/constAssertions.ts(62,10): error TS1355: A 'const' assertion can only be applied to a string, number, boolean, array, or object literal.
4+
tests/cases/conformance/expressions/typeAssertions/constAssertions.ts(63,10): error TS1355: A 'const' assertion can only be applied to a string, number, boolean, array, or object literal.
5+
6+
7+
==== tests/cases/conformance/expressions/typeAssertions/constAssertions.ts (4 errors) ====
8+
let v1 = 'abc' as const;
9+
let v2 = `abc` as const;
10+
let v3 = 10 as const;
11+
let v4 = -10 as const;
12+
let v5 = +10 as const;
13+
let v6 = 10n as const;
14+
let v7 = -10n as const;
15+
let v8 = true as const;
16+
let v9 = false as const;
17+
18+
let c1 = 'abc' as const;
19+
let c2 = `abc` as const;
20+
let c3 = 10 as const;
21+
let c4 = -10 as const;
22+
let c5 = +10 as const;
23+
let c6 = 10n as const;
24+
let c7 = -10n as const;
25+
let c8 = true as const;
26+
let c9 = false as const;
27+
28+
let vv1 = v1;
29+
let vc1 = c1;
30+
31+
let a1 = [] as const;
32+
let a2 = [1, 2, 3] as const;
33+
let a3 = [10, 'hello', true] as const;
34+
let a4 = [...[1, 2, 3]] as const;
35+
let a5 = [1, 2, 3];
36+
let a6 = [...a5] as const;
37+
let a7 = [...a6];
38+
let a8 = ['abc', ...a7] as const;
39+
let a9 = [...a8];
40+
41+
declare let d: { [x: string]: string };
42+
43+
let o1 = { x: 10, y: 20 } as const;
44+
let o2 = { a: 1, 'b': 2, ['c']: 3, d() {}, ['e' + '']: 4 } as const;
45+
let o3 = { ...o1, ...o2 } as const;
46+
let o4 = { a: 1, b: 2 };
47+
let o5 = { ...o4 } as const;
48+
let o6 = { ...o5 };
49+
let o7 = { ...d } as const;
50+
let o8 = { ...o7 };
51+
let o9 = { x: 10, foo() { this.x = 20 } } as const; // Error
52+
~
53+
!!! error TS2540: Cannot assign to 'x' because it is a read-only property.
54+
55+
let p1 = (10) as const;
56+
let p2 = ((-10)) as const;
57+
let p3 = ([(10)]) as const;
58+
let p4 = [[[[10]]]] as const;
59+
60+
let x1 = { x: 10, y: [20, 30], z: { a: { b: 42 } } } as const;
61+
62+
let q1 = <const> 10;
63+
let q2 = <const> 'abc';
64+
let q3 = <const> true;
65+
let q4 = <const> [1, 2, 3];
66+
let q5 = <const> { x: 10, y: 20 };
67+
68+
declare function id<T>(x: T): T;
69+
70+
let e1 = v1 as const; // Error
71+
~~
72+
!!! error TS1355: A 'const' assertion can only be applied to a string, number, boolean, array, or object literal.
73+
let e2 = (true ? 1 : 0) as const; // Error
74+
~~~~~~~~~~~~~~
75+
!!! error TS1355: A 'const' assertion can only be applied to a string, number, boolean, array, or object literal.
76+
let e3 = id(1) as const; // Error
77+
~~~~~
78+
!!! error TS1355: A 'const' assertion can only be applied to a string, number, boolean, array, or object literal.
79+
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
//// [constAssertions.ts]
2+
let v1 = 'abc' as const;
3+
let v2 = `abc` as const;
4+
let v3 = 10 as const;
5+
let v4 = -10 as const;
6+
let v5 = +10 as const;
7+
let v6 = 10n as const;
8+
let v7 = -10n as const;
9+
let v8 = true as const;
10+
let v9 = false as const;
11+
12+
let c1 = 'abc' as const;
13+
let c2 = `abc` as const;
14+
let c3 = 10 as const;
15+
let c4 = -10 as const;
16+
let c5 = +10 as const;
17+
let c6 = 10n as const;
18+
let c7 = -10n as const;
19+
let c8 = true as const;
20+
let c9 = false as const;
21+
22+
let vv1 = v1;
23+
let vc1 = c1;
24+
25+
let a1 = [] as const;
26+
let a2 = [1, 2, 3] as const;
27+
let a3 = [10, 'hello', true] as const;
28+
let a4 = [...[1, 2, 3]] as const;
29+
let a5 = [1, 2, 3];
30+
let a6 = [...a5] as const;
31+
let a7 = [...a6];
32+
let a8 = ['abc', ...a7] as const;
33+
let a9 = [...a8];
34+
35+
declare let d: { [x: string]: string };
36+
37+
let o1 = { x: 10, y: 20 } as const;
38+
let o2 = { a: 1, 'b': 2, ['c']: 3, d() {}, ['e' + '']: 4 } as const;
39+
let o3 = { ...o1, ...o2 } as const;
40+
let o4 = { a: 1, b: 2 };
41+
let o5 = { ...o4 } as const;
42+
let o6 = { ...o5 };
43+
let o7 = { ...d } as const;
44+
let o8 = { ...o7 };
45+
let o9 = { x: 10, foo() { this.x = 20 } } as const; // Error
46+
47+
let p1 = (10) as const;
48+
let p2 = ((-10)) as const;
49+
let p3 = ([(10)]) as const;
50+
let p4 = [[[[10]]]] as const;
51+
52+
let x1 = { x: 10, y: [20, 30], z: { a: { b: 42 } } } as const;
53+
54+
let q1 = <const> 10;
55+
let q2 = <const> 'abc';
56+
let q3 = <const> true;
57+
let q4 = <const> [1, 2, 3];
58+
let q5 = <const> { x: 10, y: 20 };
59+
60+
declare function id<T>(x: T): T;
61+
62+
let e1 = v1 as const; // Error
63+
let e2 = (true ? 1 : 0) as const; // Error
64+
let e3 = id(1) as const; // Error
65+
66+
67+
//// [constAssertions.js]
68+
"use strict";
69+
let v1 = 'abc';
70+
let v2 = `abc`;
71+
let v3 = 10;
72+
let v4 = -10;
73+
let v5 = +10;
74+
let v6 = 10n;
75+
let v7 = -10n;
76+
let v8 = true;
77+
let v9 = false;
78+
let c1 = 'abc';
79+
let c2 = `abc`;
80+
let c3 = 10;
81+
let c4 = -10;
82+
let c5 = +10;
83+
let c6 = 10n;
84+
let c7 = -10n;
85+
let c8 = true;
86+
let c9 = false;
87+
let vv1 = v1;
88+
let vc1 = c1;
89+
let a1 = [];
90+
let a2 = [1, 2, 3];
91+
let a3 = [10, 'hello', true];
92+
let a4 = [...[1, 2, 3]];
93+
let a5 = [1, 2, 3];
94+
let a6 = [...a5];
95+
let a7 = [...a6];
96+
let a8 = ['abc', ...a7];
97+
let a9 = [...a8];
98+
let o1 = { x: 10, y: 20 };
99+
let o2 = { a: 1, 'b': 2, ['c']: 3, d() { }, ['e' + '']: 4 };
100+
let o3 = { ...o1, ...o2 };
101+
let o4 = { a: 1, b: 2 };
102+
let o5 = { ...o4 };
103+
let o6 = { ...o5 };
104+
let o7 = { ...d };
105+
let o8 = { ...o7 };
106+
let o9 = { x: 10, foo() { this.x = 20; } }; // Error
107+
let p1 = (10);
108+
let p2 = ((-10));
109+
let p3 = ([(10)]);
110+
let p4 = [[[[10]]]];
111+
let x1 = { x: 10, y: [20, 30], z: { a: { b: 42 } } };
112+
let q1 = 10;
113+
let q2 = 'abc';
114+
let q3 = true;
115+
let q4 = [1, 2, 3];
116+
let q5 = { x: 10, y: 20 };
117+
let e1 = v1; // Error
118+
let e2 = (true ? 1 : 0); // Error
119+
let e3 = id(1); // Error
120+
121+
122+
//// [constAssertions.d.ts]
123+
declare let v1: "abc";
124+
declare let v2: "abc";
125+
declare let v3: 10;
126+
declare let v4: -10;
127+
declare let v5: 10;
128+
declare let v6: 10n;
129+
declare let v7: -10n;
130+
declare let v8: true;
131+
declare let v9: false;
132+
declare let c1: "abc";
133+
declare let c2: "abc";
134+
declare let c3: 10;
135+
declare let c4: -10;
136+
declare let c5: 10;
137+
declare let c6: 10n;
138+
declare let c7: -10n;
139+
declare let c8: true;
140+
declare let c9: false;
141+
declare let vv1: "abc";
142+
declare let vc1: "abc";
143+
declare let a1: readonly [];
144+
declare let a2: readonly [1, 2, 3];
145+
declare let a3: readonly [10, "hello", true];
146+
declare let a4: readonly (1 | 2 | 3)[];
147+
declare let a5: number[];
148+
declare let a6: readonly number[];
149+
declare let a7: number[];
150+
declare let a8: readonly ["abc", ...number[]];
151+
declare let a9: (number | "abc")[];
152+
declare let d: {
153+
[x: string]: string;
154+
};
155+
declare let o1: {
156+
readonly x: 10;
157+
readonly y: 20;
158+
};
159+
declare let o2: {
160+
readonly [x: string]: 1 | 2 | 3 | (() => void) | 4;
161+
readonly a: 1;
162+
readonly 'b': 2;
163+
readonly ['c']: 3;
164+
readonly d: () => void;
165+
};
166+
declare let o3: {
167+
readonly a: 1;
168+
readonly 'b': 2;
169+
readonly ['c']: 3;
170+
readonly d: () => void;
171+
readonly x: 10;
172+
readonly y: 20;
173+
};
174+
declare let o4: {
175+
a: number;
176+
b: number;
177+
};
178+
declare let o5: {
179+
readonly a: number;
180+
readonly b: number;
181+
};
182+
declare let o6: {
183+
a: number;
184+
b: number;
185+
};
186+
declare let o7: {
187+
readonly [x: string]: string;
188+
};
189+
declare let o8: {
190+
[x: string]: string;
191+
};
192+
declare let o9: {
193+
readonly x: 10;
194+
readonly foo: () => void;
195+
};
196+
declare let p1: 10;
197+
declare let p2: -10;
198+
declare let p3: readonly [10];
199+
declare let p4: readonly [readonly [readonly [readonly [10]]]];
200+
declare let x1: {
201+
readonly x: 10;
202+
readonly y: readonly [20, 30];
203+
z: {
204+
a: {
205+
readonly b: 42;
206+
};
207+
};
208+
};
209+
declare let q1: 10;
210+
declare let q2: "abc";
211+
declare let q3: true;
212+
declare let q4: readonly [1, 2, 3];
213+
declare let q5: {
214+
readonly x: 10;
215+
readonly y: 20;
216+
};
217+
declare function id<T>(x: T): T;
218+
declare let e1: "abc";
219+
declare let e2: 0 | 1;
220+
declare let e3: 1;

0 commit comments

Comments
 (0)