Skip to content

Commit 1539234

Browse files
authored
Ban old-style type assertions under erasableSyntaxOnly (#61244)
1 parent 011f7e4 commit 1539234

File tree

6 files changed

+362
-1
lines changed

6 files changed

+362
-1
lines changed

src/compiler/checker.ts

+5
Original file line numberDiff line numberDiff line change
@@ -37312,6 +37312,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3731237312
if (file && fileExtensionIsOneOf(file.fileName, [Extension.Cts, Extension.Mts])) {
3731337313
grammarErrorOnNode(node, Diagnostics.This_syntax_is_reserved_in_files_with_the_mts_or_cts_extension_Use_an_as_expression_instead);
3731437314
}
37315+
if (compilerOptions.erasableSyntaxOnly) {
37316+
const start = node.type.pos - "<".length;
37317+
const end = skipTrivia(file.text, node.type.end) + ">".length;
37318+
diagnostics.add(createFileDiagnostic(file, start, end - start, Diagnostics.This_syntax_is_not_allowed_when_erasableSyntaxOnly_is_enabled));
37319+
}
3731537320
}
3731637321
return checkAssertionWorker(node, checkMode);
3731737322
}

tests/baselines/reference/erasableSyntaxOnly.errors.txt

+69-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
error TS2318: Cannot find global type 'IterableIterator'.
12
commonjs.cts(1,1): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
23
commonjs.cts(2,1): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
34
index.ts(3,17): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
@@ -8,9 +9,22 @@ index.ts(17,15): error TS1294: This syntax is not allowed when 'erasableSyntaxOn
89
index.ts(22,6): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
910
index.ts(26,1): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
1011
index.ts(28,12): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
12+
index.ts(67,6): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
13+
index.ts(68,6): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
14+
index.ts(69,7): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
15+
index.ts(72,6): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
16+
index.ts(73,7): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
17+
index.ts(74,1): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
18+
index.ts(79,11): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
19+
index.ts(81,12): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
20+
index.ts(86,1): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
21+
index.ts(89,1): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
22+
index.ts(90,1): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
23+
index.ts(94,1): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
1124

1225

13-
==== index.ts (8 errors) ====
26+
!!! error TS2318: Cannot find global type 'IterableIterator'.
27+
==== index.ts (20 errors) ====
1428
class MyClassErr {
1529
// No parameter properties
1630
constructor(public foo: string) { }
@@ -92,6 +106,60 @@ index.ts(28,12): error TS1294: This syntax is not allowed when 'erasableSyntaxOn
92106
import FineAlias = EnumInAmbientContext.B;
93107
}
94108

109+
// Not erasable
110+
(()=><any>{})();
111+
~~~~~
112+
!!! error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
113+
(()=>< any >{})();
114+
~~~~~~~
115+
!!! error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
116+
(()=> < any > {})();
117+
~~~~~~~
118+
!!! error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
119+
120+
// Erasable
121+
(()=><any>({}))();
122+
~~~~~
123+
!!! error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
124+
(()=>(<any>{}))();
125+
~~~~~
126+
!!! error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
127+
<any>{};
128+
~~~~~
129+
!!! error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
130+
131+
132+
// return and yield ASI
133+
function *gen() {
134+
yield <any>
135+
~~~~~
136+
!!! error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
137+
1;
138+
return <any>
139+
~~~~~
140+
!!! error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
141+
1;
142+
}
143+
144+
// at the start of an ExpressionStatement if followed by an object literal; though I'm not sure why one would use it there
145+
<unknown>{foo() {}}.foo();
146+
~~~~~~~~~
147+
!!! error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
148+
149+
// at the start of an ExpressionStatement if followed by function keyword
150+
<unknown>function() {}();
151+
~~~~~~~~~
152+
!!! error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
153+
<unknown>function() {};
154+
~~~~~~~~~
155+
!!! error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
156+
157+
// at the start of an ExpressionStatement if followed by an anonymous class expression
158+
// note that this exact syntax currently emits invalid JS (no parenthesis added like for function above)
159+
<unknown>class {}
160+
~~~~~~~~~
161+
!!! error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
162+
95163
==== commonjs.cts (2 errors) ====
96164
import foo = require("./other.cjs");
97165
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

tests/baselines/reference/erasableSyntaxOnly.js

+88
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,36 @@ declare namespace AmbientStuff {
6565

6666
import FineAlias = EnumInAmbientContext.B;
6767
}
68+
69+
// Not erasable
70+
(()=><any>{})();
71+
(()=>< any >{})();
72+
(()=> < any > {})();
73+
74+
// Erasable
75+
(()=><any>({}))();
76+
(()=>(<any>{}))();
77+
<any>{};
78+
79+
80+
// return and yield ASI
81+
function *gen() {
82+
yield <any>
83+
1;
84+
return <any>
85+
1;
86+
}
87+
88+
// at the start of an ExpressionStatement if followed by an object literal; though I'm not sure why one would use it there
89+
<unknown>{foo() {}}.foo();
90+
91+
// at the start of an ExpressionStatement if followed by function keyword
92+
<unknown>function() {}();
93+
<unknown>function() {};
94+
95+
// at the start of an ExpressionStatement if followed by an anonymous class expression
96+
// note that this exact syntax currently emits invalid JS (no parenthesis added like for function above)
97+
<unknown>class {}
6898

6999
//// [commonjs.cts]
70100
import foo = require("./other.cjs");
@@ -82,6 +112,33 @@ export default foo;
82112

83113

84114
//// [index.js]
115+
var __generator = (this && this.__generator) || function (thisArg, body) {
116+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
117+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
118+
function verb(n) { return function (v) { return step([n, v]); }; }
119+
function step(op) {
120+
if (f) throw new TypeError("Generator is already executing.");
121+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
122+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
123+
if (y = 0, t) op = [op[0] & 2, t.value];
124+
switch (op[0]) {
125+
case 0: case 1: t = op; break;
126+
case 4: _.label++; return { value: op[1], done: false };
127+
case 5: _.label++; y = op[1]; op = [0]; continue;
128+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
129+
default:
130+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
131+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
132+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
133+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
134+
if (t[2]) _.ops.pop();
135+
_.trys.pop(); continue;
136+
}
137+
op = body.call(thisArg, _);
138+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
139+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
140+
}
141+
};
85142
var MyClassErr = /** @class */ (function () {
86143
// No parameter properties
87144
function MyClassErr(foo) {
@@ -120,6 +177,37 @@ var MyClassOk = /** @class */ (function () {
120177
}
121178
return MyClassOk;
122179
}());
180+
// Not erasable
181+
(function () { return ({}); })();
182+
(function () { return ({}); })();
183+
(function () { return ({}); })();
184+
// Erasable
185+
(function () { return ({}); })();
186+
(function () { return ({}); })();
187+
({});
188+
// return and yield ASI
189+
function gen() {
190+
return __generator(this, function (_a) {
191+
switch (_a.label) {
192+
case 0: return [4 /*yield*/, 1];
193+
case 1:
194+
_a.sent();
195+
return [2 /*return*/, 1];
196+
}
197+
});
198+
}
199+
// at the start of an ExpressionStatement if followed by an object literal; though I'm not sure why one would use it there
200+
({ foo: function () { } }.foo());
201+
// at the start of an ExpressionStatement if followed by function keyword
202+
(function () { })();
203+
(function () { });
204+
// at the start of an ExpressionStatement if followed by an anonymous class expression
205+
// note that this exact syntax currently emits invalid JS (no parenthesis added like for function above)
206+
/** @class */ (function () {
207+
function class_1() {
208+
}
209+
return class_1;
210+
}());
123211
//// [commonjs.cjs]
124212
"use strict";
125213
var foo = require("./other.cjs");

tests/baselines/reference/erasableSyntaxOnly.symbols

+35
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,41 @@ declare namespace AmbientStuff {
118118
>B : Symbol(FineAlias, Decl(index.ts, 58, 31))
119119
}
120120

121+
// Not erasable
122+
(()=><any>{})();
123+
(()=>< any >{})();
124+
(()=> < any > {})();
125+
126+
// Erasable
127+
(()=><any>({}))();
128+
(()=>(<any>{}))();
129+
<any>{};
130+
131+
132+
// return and yield ASI
133+
function *gen() {
134+
>gen : Symbol(gen, Decl(index.ts, 73, 8))
135+
136+
yield <any>
137+
1;
138+
return <any>
139+
1;
140+
}
141+
142+
// at the start of an ExpressionStatement if followed by an object literal; though I'm not sure why one would use it there
143+
<unknown>{foo() {}}.foo();
144+
>{foo() {}}.foo : Symbol(foo, Decl(index.ts, 85, 10))
145+
>foo : Symbol(foo, Decl(index.ts, 85, 10))
146+
>foo : Symbol(foo, Decl(index.ts, 85, 10))
147+
148+
// at the start of an ExpressionStatement if followed by function keyword
149+
<unknown>function() {}();
150+
<unknown>function() {};
151+
152+
// at the start of an ExpressionStatement if followed by an anonymous class expression
153+
// note that this exact syntax currently emits invalid JS (no parenthesis added like for function above)
154+
<unknown>class {}
155+
121156
=== commonjs.cts ===
122157
import foo = require("./other.cjs");
123158
>foo : Symbol(foo, Decl(commonjs.cts, 0, 0))

tests/baselines/reference/erasableSyntaxOnly.types

+135
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,141 @@ declare namespace AmbientStuff {
160160
> : ^^^^^^^^^^^^^^^^^^^^^^
161161
}
162162

163+
// Not erasable
164+
(()=><any>{})();
165+
>(()=><any>{})() : any
166+
> : ^^^
167+
>(()=><any>{}) : () => any
168+
> : ^^^^^^
169+
>()=><any>{} : () => any
170+
> : ^^^^^^
171+
><any>{} : any
172+
> : ^^^
173+
>{} : {}
174+
> : ^^
175+
176+
(()=>< any >{})();
177+
>(()=>< any >{})() : any
178+
> : ^^^
179+
>(()=>< any >{}) : () => any
180+
> : ^^^^^^
181+
>()=>< any >{} : () => any
182+
> : ^^^^^^
183+
>< any >{} : any
184+
> : ^^^
185+
>{} : {}
186+
> : ^^
187+
188+
(()=> < any > {})();
189+
>(()=> < any > {})() : any
190+
> : ^^^
191+
>(()=> < any > {}) : () => any
192+
> : ^^^^^^
193+
>()=> < any > {} : () => any
194+
> : ^^^^^^
195+
>< any > {} : any
196+
> : ^^^
197+
>{} : {}
198+
> : ^^
199+
200+
// Erasable
201+
(()=><any>({}))();
202+
>(()=><any>({}))() : any
203+
> : ^^^
204+
>(()=><any>({})) : () => any
205+
> : ^^^^^^
206+
>()=><any>({}) : () => any
207+
> : ^^^^^^
208+
><any>({}) : any
209+
> : ^^^
210+
>({}) : {}
211+
> : ^^
212+
>{} : {}
213+
> : ^^
214+
215+
(()=>(<any>{}))();
216+
>(()=>(<any>{}))() : any
217+
> : ^^^
218+
>(()=>(<any>{})) : () => any
219+
> : ^^^^^^^^^
220+
>()=>(<any>{}) : () => any
221+
> : ^^^^^^^^^
222+
>(<any>{}) : any
223+
> : ^^^
224+
><any>{} : any
225+
> : ^^^
226+
>{} : {}
227+
> : ^^
228+
229+
<any>{};
230+
><any>{} : any
231+
> : ^^^
232+
>{} : {}
233+
> : ^^
234+
235+
236+
// return and yield ASI
237+
function *gen() {
238+
>gen : () => {}
239+
> : ^^^^^^^^
240+
241+
yield <any>
242+
>yield <any> 1 : any
243+
> : ^^^
244+
><any> 1 : any
245+
> : ^^^
246+
247+
1;
248+
>1 : 1
249+
> : ^
250+
251+
return <any>
252+
><any> 1 : any
253+
> : ^^^
254+
255+
1;
256+
>1 : 1
257+
> : ^
258+
}
259+
260+
// at the start of an ExpressionStatement if followed by an object literal; though I'm not sure why one would use it there
261+
<unknown>{foo() {}}.foo();
262+
><unknown>{foo() {}}.foo() : unknown
263+
> : ^^^^^^^
264+
>{foo() {}}.foo() : void
265+
> : ^^^^
266+
>{foo() {}}.foo : () => void
267+
> : ^^^^^^^^^^
268+
>{foo() {}} : { foo(): void; }
269+
> : ^^^^^^^^^^^^^^^^
270+
>foo : () => void
271+
> : ^^^^^^^^^^
272+
>foo : () => void
273+
> : ^^^^^^^^^^
274+
275+
// at the start of an ExpressionStatement if followed by function keyword
276+
<unknown>function() {}();
277+
><unknown>function() {}() : unknown
278+
> : ^^^^^^^
279+
>function() {}() : void
280+
> : ^^^^
281+
>function() {} : () => void
282+
> : ^^^^^^^^^^
283+
284+
<unknown>function() {};
285+
><unknown>function() {} : unknown
286+
> : ^^^^^^^
287+
>function() {} : () => void
288+
> : ^^^^^^^^^^
289+
290+
// at the start of an ExpressionStatement if followed by an anonymous class expression
291+
// note that this exact syntax currently emits invalid JS (no parenthesis added like for function above)
292+
<unknown>class {}
293+
><unknown>class {} : unknown
294+
> : ^^^^^^^
295+
>class {} : typeof (Anonymous class)
296+
> : ^^^^^^^^^^^^^^^^^^^^^^^^
297+
163298
=== commonjs.cts ===
164299
import foo = require("./other.cjs");
165300
>foo : () => void

0 commit comments

Comments
 (0)