Skip to content

Commit 1ed8674

Browse files
Allow accessor properties in ambient contexts when targeting ES5 (#61927)
Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: RyanCavanaugh <[email protected]>
1 parent d6c3ac3 commit 1ed8674

File tree

6 files changed

+258
-1
lines changed

6 files changed

+258
-1
lines changed

src/compiler/checker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53039,7 +53039,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
5303953039
if (languageVersion < ScriptTarget.ES2015 && isPrivateIdentifier(node.name)) {
5304053040
return grammarErrorOnNode(node.name, Diagnostics.Private_identifiers_are_only_available_when_targeting_ECMAScript_2015_and_higher);
5304153041
}
53042-
if (languageVersion < ScriptTarget.ES2015 && isAutoAccessorPropertyDeclaration(node)) {
53042+
if (languageVersion < ScriptTarget.ES2015 && isAutoAccessorPropertyDeclaration(node) && !(node.flags & NodeFlags.Ambient)) {
5304353043
return grammarErrorOnNode(node.name, Diagnostics.Properties_with_the_accessor_modifier_are_only_available_when_targeting_ECMAScript_2015_and_higher);
5304453044
}
5304553045
if (isAutoAccessorPropertyDeclaration(node) && checkGrammarForInvalidQuestionMark(node.questionToken, Diagnostics.An_accessor_property_cannot_be_declared_optional)) {
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
accessorInAmbientContextES5.ts(25,14): error TS18045: Properties with the 'accessor' modifier are only available when targeting ECMAScript 2015 and higher.
2+
3+
4+
==== accessorInAmbientContextES5.ts (1 errors) ====
5+
// Should allow accessor in ambient contexts even when targeting ES5
6+
7+
declare class AmbientClass {
8+
accessor prop1: string;
9+
static accessor prop2: number;
10+
private accessor prop3: boolean;
11+
private static accessor prop4: symbol;
12+
}
13+
14+
declare namespace AmbientNamespace {
15+
class C {
16+
accessor prop: string;
17+
}
18+
}
19+
20+
// Should also work in .d.ts files (simulated with declare)
21+
declare module "some-module" {
22+
export class ExportedClass {
23+
accessor value: any;
24+
}
25+
}
26+
27+
// Regular class should still error when targeting ES5
28+
class RegularClass {
29+
accessor shouldError: string; // Should still error
30+
~~~~~~~~~~~
31+
!!! error TS18045: Properties with the 'accessor' modifier are only available when targeting ECMAScript 2015 and higher.
32+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
//// [tests/cases/compiler/accessorInAmbientContextES5.ts] ////
2+
3+
//// [accessorInAmbientContextES5.ts]
4+
// Should allow accessor in ambient contexts even when targeting ES5
5+
6+
declare class AmbientClass {
7+
accessor prop1: string;
8+
static accessor prop2: number;
9+
private accessor prop3: boolean;
10+
private static accessor prop4: symbol;
11+
}
12+
13+
declare namespace AmbientNamespace {
14+
class C {
15+
accessor prop: string;
16+
}
17+
}
18+
19+
// Should also work in .d.ts files (simulated with declare)
20+
declare module "some-module" {
21+
export class ExportedClass {
22+
accessor value: any;
23+
}
24+
}
25+
26+
// Regular class should still error when targeting ES5
27+
class RegularClass {
28+
accessor shouldError: string; // Should still error
29+
}
30+
31+
//// [accessorInAmbientContextES5.js]
32+
// Should allow accessor in ambient contexts even when targeting ES5
33+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
34+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
35+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
36+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
37+
};
38+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
39+
if (kind === "m") throw new TypeError("Private method is not writable");
40+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
41+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
42+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
43+
};
44+
var _RegularClass_shouldError_accessor_storage;
45+
// Regular class should still error when targeting ES5
46+
var RegularClass = /** @class */ (function () {
47+
function RegularClass() {
48+
_RegularClass_shouldError_accessor_storage.set(this, void 0);
49+
}
50+
Object.defineProperty(RegularClass.prototype, "shouldError", {
51+
get: function () { return __classPrivateFieldGet(this, _RegularClass_shouldError_accessor_storage, "f"); } // Should still error
52+
,
53+
set: function (value) { __classPrivateFieldSet(this, _RegularClass_shouldError_accessor_storage, value, "f"); },
54+
enumerable: false,
55+
configurable: true
56+
});
57+
return RegularClass;
58+
}());
59+
_RegularClass_shouldError_accessor_storage = new WeakMap();
60+
61+
62+
//// [accessorInAmbientContextES5.d.ts]
63+
declare class AmbientClass {
64+
accessor prop1: string;
65+
static accessor prop2: number;
66+
private accessor prop3;
67+
private static accessor prop4;
68+
}
69+
declare namespace AmbientNamespace {
70+
class C {
71+
accessor prop: string;
72+
}
73+
}
74+
declare module "some-module" {
75+
class ExportedClass {
76+
accessor value: any;
77+
}
78+
}
79+
declare class RegularClass {
80+
accessor shouldError: string;
81+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//// [tests/cases/compiler/accessorInAmbientContextES5.ts] ////
2+
3+
=== accessorInAmbientContextES5.ts ===
4+
// Should allow accessor in ambient contexts even when targeting ES5
5+
6+
declare class AmbientClass {
7+
>AmbientClass : Symbol(AmbientClass, Decl(accessorInAmbientContextES5.ts, 0, 0))
8+
9+
accessor prop1: string;
10+
>prop1 : Symbol(AmbientClass.prop1, Decl(accessorInAmbientContextES5.ts, 2, 28))
11+
12+
static accessor prop2: number;
13+
>prop2 : Symbol(AmbientClass.prop2, Decl(accessorInAmbientContextES5.ts, 3, 27))
14+
15+
private accessor prop3: boolean;
16+
>prop3 : Symbol(AmbientClass.prop3, Decl(accessorInAmbientContextES5.ts, 4, 34))
17+
18+
private static accessor prop4: symbol;
19+
>prop4 : Symbol(AmbientClass.prop4, Decl(accessorInAmbientContextES5.ts, 5, 36))
20+
}
21+
22+
declare namespace AmbientNamespace {
23+
>AmbientNamespace : Symbol(AmbientNamespace, Decl(accessorInAmbientContextES5.ts, 7, 1))
24+
25+
class C {
26+
>C : Symbol(C, Decl(accessorInAmbientContextES5.ts, 9, 36))
27+
28+
accessor prop: string;
29+
>prop : Symbol(C.prop, Decl(accessorInAmbientContextES5.ts, 10, 13))
30+
}
31+
}
32+
33+
// Should also work in .d.ts files (simulated with declare)
34+
declare module "some-module" {
35+
>"some-module" : Symbol("some-module", Decl(accessorInAmbientContextES5.ts, 13, 1))
36+
37+
export class ExportedClass {
38+
>ExportedClass : Symbol(ExportedClass, Decl(accessorInAmbientContextES5.ts, 16, 30))
39+
40+
accessor value: any;
41+
>value : Symbol(ExportedClass.value, Decl(accessorInAmbientContextES5.ts, 17, 32))
42+
}
43+
}
44+
45+
// Regular class should still error when targeting ES5
46+
class RegularClass {
47+
>RegularClass : Symbol(RegularClass, Decl(accessorInAmbientContextES5.ts, 20, 1))
48+
49+
accessor shouldError: string; // Should still error
50+
>shouldError : Symbol(RegularClass.shouldError, Decl(accessorInAmbientContextES5.ts, 23, 20))
51+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//// [tests/cases/compiler/accessorInAmbientContextES5.ts] ////
2+
3+
=== accessorInAmbientContextES5.ts ===
4+
// Should allow accessor in ambient contexts even when targeting ES5
5+
6+
declare class AmbientClass {
7+
>AmbientClass : AmbientClass
8+
> : ^^^^^^^^^^^^
9+
10+
accessor prop1: string;
11+
>prop1 : string
12+
> : ^^^^^^
13+
14+
static accessor prop2: number;
15+
>prop2 : number
16+
> : ^^^^^^
17+
18+
private accessor prop3: boolean;
19+
>prop3 : boolean
20+
> : ^^^^^^^
21+
22+
private static accessor prop4: symbol;
23+
>prop4 : symbol
24+
> : ^^^^^^
25+
}
26+
27+
declare namespace AmbientNamespace {
28+
>AmbientNamespace : typeof AmbientNamespace
29+
> : ^^^^^^^^^^^^^^^^^^^^^^^
30+
31+
class C {
32+
>C : C
33+
> : ^
34+
35+
accessor prop: string;
36+
>prop : string
37+
> : ^^^^^^
38+
}
39+
}
40+
41+
// Should also work in .d.ts files (simulated with declare)
42+
declare module "some-module" {
43+
>"some-module" : typeof import("some-module")
44+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
45+
46+
export class ExportedClass {
47+
>ExportedClass : ExportedClass
48+
> : ^^^^^^^^^^^^^
49+
50+
accessor value: any;
51+
>value : any
52+
> : ^^^
53+
}
54+
}
55+
56+
// Regular class should still error when targeting ES5
57+
class RegularClass {
58+
>RegularClass : RegularClass
59+
> : ^^^^^^^^^^^^
60+
61+
accessor shouldError: string; // Should still error
62+
>shouldError : string
63+
> : ^^^^^^
64+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// @target: es5
2+
// @declaration: true
3+
4+
// Should allow accessor in ambient contexts even when targeting ES5
5+
6+
declare class AmbientClass {
7+
accessor prop1: string;
8+
static accessor prop2: number;
9+
private accessor prop3: boolean;
10+
private static accessor prop4: symbol;
11+
}
12+
13+
declare namespace AmbientNamespace {
14+
class C {
15+
accessor prop: string;
16+
}
17+
}
18+
19+
// Should also work in .d.ts files (simulated with declare)
20+
declare module "some-module" {
21+
export class ExportedClass {
22+
accessor value: any;
23+
}
24+
}
25+
26+
// Regular class should still error when targeting ES5
27+
class RegularClass {
28+
accessor shouldError: string; // Should still error
29+
}

0 commit comments

Comments
 (0)