diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 76e81a959790b..ff2315db5c6bb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -53029,7 +53029,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (languageVersion < ScriptTarget.ES2015 && isPrivateIdentifier(node.name)) { return grammarErrorOnNode(node.name, Diagnostics.Private_identifiers_are_only_available_when_targeting_ECMAScript_2015_and_higher); } - if (languageVersion < ScriptTarget.ES2015 && isAutoAccessorPropertyDeclaration(node)) { + if (languageVersion < ScriptTarget.ES2015 && isAutoAccessorPropertyDeclaration(node) && !(node.flags & NodeFlags.Ambient)) { return grammarErrorOnNode(node.name, Diagnostics.Properties_with_the_accessor_modifier_are_only_available_when_targeting_ECMAScript_2015_and_higher); } if (isAutoAccessorPropertyDeclaration(node) && checkGrammarForInvalidQuestionMark(node.questionToken, Diagnostics.An_accessor_property_cannot_be_declared_optional)) { diff --git a/tests/baselines/reference/accessorInAmbientContextES5.errors.txt b/tests/baselines/reference/accessorInAmbientContextES5.errors.txt new file mode 100644 index 0000000000000..c9351f69f7213 --- /dev/null +++ b/tests/baselines/reference/accessorInAmbientContextES5.errors.txt @@ -0,0 +1,32 @@ +accessorInAmbientContextES5.ts(25,14): error TS18045: Properties with the 'accessor' modifier are only available when targeting ECMAScript 2015 and higher. + + +==== accessorInAmbientContextES5.ts (1 errors) ==== + // Should allow accessor in ambient contexts even when targeting ES5 + + declare class AmbientClass { + accessor prop1: string; + static accessor prop2: number; + private accessor prop3: boolean; + private static accessor prop4: symbol; + } + + declare namespace AmbientNamespace { + class C { + accessor prop: string; + } + } + + // Should also work in .d.ts files (simulated with declare) + declare module "some-module" { + export class ExportedClass { + accessor value: any; + } + } + + // Regular class should still error when targeting ES5 + class RegularClass { + accessor shouldError: string; // Should still error + ~~~~~~~~~~~ +!!! error TS18045: Properties with the 'accessor' modifier are only available when targeting ECMAScript 2015 and higher. + } \ No newline at end of file diff --git a/tests/baselines/reference/accessorInAmbientContextES5.js b/tests/baselines/reference/accessorInAmbientContextES5.js new file mode 100644 index 0000000000000..caea4933da878 --- /dev/null +++ b/tests/baselines/reference/accessorInAmbientContextES5.js @@ -0,0 +1,81 @@ +//// [tests/cases/compiler/accessorInAmbientContextES5.ts] //// + +//// [accessorInAmbientContextES5.ts] +// Should allow accessor in ambient contexts even when targeting ES5 + +declare class AmbientClass { + accessor prop1: string; + static accessor prop2: number; + private accessor prop3: boolean; + private static accessor prop4: symbol; +} + +declare namespace AmbientNamespace { + class C { + accessor prop: string; + } +} + +// Should also work in .d.ts files (simulated with declare) +declare module "some-module" { + export class ExportedClass { + accessor value: any; + } +} + +// Regular class should still error when targeting ES5 +class RegularClass { + accessor shouldError: string; // Should still error +} + +//// [accessorInAmbientContextES5.js] +// Should allow accessor in ambient contexts even when targeting ES5 +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + 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"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + 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"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var _RegularClass_shouldError_accessor_storage; +// Regular class should still error when targeting ES5 +var RegularClass = /** @class */ (function () { + function RegularClass() { + _RegularClass_shouldError_accessor_storage.set(this, void 0); + } + Object.defineProperty(RegularClass.prototype, "shouldError", { + get: function () { return __classPrivateFieldGet(this, _RegularClass_shouldError_accessor_storage, "f"); } // Should still error + , + set: function (value) { __classPrivateFieldSet(this, _RegularClass_shouldError_accessor_storage, value, "f"); }, + enumerable: false, + configurable: true + }); + return RegularClass; +}()); +_RegularClass_shouldError_accessor_storage = new WeakMap(); + + +//// [accessorInAmbientContextES5.d.ts] +declare class AmbientClass { + accessor prop1: string; + static accessor prop2: number; + private accessor prop3; + private static accessor prop4; +} +declare namespace AmbientNamespace { + class C { + accessor prop: string; + } +} +declare module "some-module" { + class ExportedClass { + accessor value: any; + } +} +declare class RegularClass { + accessor shouldError: string; +} diff --git a/tests/baselines/reference/accessorInAmbientContextES5.symbols b/tests/baselines/reference/accessorInAmbientContextES5.symbols new file mode 100644 index 0000000000000..c37f91917d28c --- /dev/null +++ b/tests/baselines/reference/accessorInAmbientContextES5.symbols @@ -0,0 +1,51 @@ +//// [tests/cases/compiler/accessorInAmbientContextES5.ts] //// + +=== accessorInAmbientContextES5.ts === +// Should allow accessor in ambient contexts even when targeting ES5 + +declare class AmbientClass { +>AmbientClass : Symbol(AmbientClass, Decl(accessorInAmbientContextES5.ts, 0, 0)) + + accessor prop1: string; +>prop1 : Symbol(AmbientClass.prop1, Decl(accessorInAmbientContextES5.ts, 2, 28)) + + static accessor prop2: number; +>prop2 : Symbol(AmbientClass.prop2, Decl(accessorInAmbientContextES5.ts, 3, 27)) + + private accessor prop3: boolean; +>prop3 : Symbol(AmbientClass.prop3, Decl(accessorInAmbientContextES5.ts, 4, 34)) + + private static accessor prop4: symbol; +>prop4 : Symbol(AmbientClass.prop4, Decl(accessorInAmbientContextES5.ts, 5, 36)) +} + +declare namespace AmbientNamespace { +>AmbientNamespace : Symbol(AmbientNamespace, Decl(accessorInAmbientContextES5.ts, 7, 1)) + + class C { +>C : Symbol(C, Decl(accessorInAmbientContextES5.ts, 9, 36)) + + accessor prop: string; +>prop : Symbol(C.prop, Decl(accessorInAmbientContextES5.ts, 10, 13)) + } +} + +// Should also work in .d.ts files (simulated with declare) +declare module "some-module" { +>"some-module" : Symbol("some-module", Decl(accessorInAmbientContextES5.ts, 13, 1)) + + export class ExportedClass { +>ExportedClass : Symbol(ExportedClass, Decl(accessorInAmbientContextES5.ts, 16, 30)) + + accessor value: any; +>value : Symbol(ExportedClass.value, Decl(accessorInAmbientContextES5.ts, 17, 32)) + } +} + +// Regular class should still error when targeting ES5 +class RegularClass { +>RegularClass : Symbol(RegularClass, Decl(accessorInAmbientContextES5.ts, 20, 1)) + + accessor shouldError: string; // Should still error +>shouldError : Symbol(RegularClass.shouldError, Decl(accessorInAmbientContextES5.ts, 23, 20)) +} diff --git a/tests/baselines/reference/accessorInAmbientContextES5.types b/tests/baselines/reference/accessorInAmbientContextES5.types new file mode 100644 index 0000000000000..eefedf0cf1306 --- /dev/null +++ b/tests/baselines/reference/accessorInAmbientContextES5.types @@ -0,0 +1,64 @@ +//// [tests/cases/compiler/accessorInAmbientContextES5.ts] //// + +=== accessorInAmbientContextES5.ts === +// Should allow accessor in ambient contexts even when targeting ES5 + +declare class AmbientClass { +>AmbientClass : AmbientClass +> : ^^^^^^^^^^^^ + + accessor prop1: string; +>prop1 : string +> : ^^^^^^ + + static accessor prop2: number; +>prop2 : number +> : ^^^^^^ + + private accessor prop3: boolean; +>prop3 : boolean +> : ^^^^^^^ + + private static accessor prop4: symbol; +>prop4 : symbol +> : ^^^^^^ +} + +declare namespace AmbientNamespace { +>AmbientNamespace : typeof AmbientNamespace +> : ^^^^^^^^^^^^^^^^^^^^^^^ + + class C { +>C : C +> : ^ + + accessor prop: string; +>prop : string +> : ^^^^^^ + } +} + +// Should also work in .d.ts files (simulated with declare) +declare module "some-module" { +>"some-module" : typeof import("some-module") +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + export class ExportedClass { +>ExportedClass : ExportedClass +> : ^^^^^^^^^^^^^ + + accessor value: any; +>value : any +> : ^^^ + } +} + +// Regular class should still error when targeting ES5 +class RegularClass { +>RegularClass : RegularClass +> : ^^^^^^^^^^^^ + + accessor shouldError: string; // Should still error +>shouldError : string +> : ^^^^^^ +} diff --git a/tests/cases/compiler/accessorInAmbientContextES5.ts b/tests/cases/compiler/accessorInAmbientContextES5.ts new file mode 100644 index 0000000000000..42fb79e9774cf --- /dev/null +++ b/tests/cases/compiler/accessorInAmbientContextES5.ts @@ -0,0 +1,29 @@ +// @target: es5 +// @declaration: true + +// Should allow accessor in ambient contexts even when targeting ES5 + +declare class AmbientClass { + accessor prop1: string; + static accessor prop2: number; + private accessor prop3: boolean; + private static accessor prop4: symbol; +} + +declare namespace AmbientNamespace { + class C { + accessor prop: string; + } +} + +// Should also work in .d.ts files (simulated with declare) +declare module "some-module" { + export class ExportedClass { + accessor value: any; + } +} + +// Regular class should still error when targeting ES5 +class RegularClass { + accessor shouldError: string; // Should still error +} \ No newline at end of file