diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e18a3bf0da2e9..843048f245e41 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -26815,6 +26815,12 @@ namespace ts { if (!prop && checkPrivateIdentifierPropertyAccess(leftType, right, lexicallyScopedSymbol)) { return errorType; } + else { + const isSetonlyAccessor = prop && prop.flags & SymbolFlags.SetAccessor && !(prop.flags & SymbolFlags.GetAccessor); + if (isSetonlyAccessor && !isAssignmentTarget(node)) { + error(node, Diagnostics.Private_accessor_was_defined_without_a_getter); + } + } } else { if (isAnyLike) { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index f020c6814224a..4a2284effa353 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3296,6 +3296,10 @@ "category": "Error", "code": 2805 }, + "Private accessor was defined without a getter.": { + "category": "Error", + "code": 2806 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 1c459c83e64eb..450dbedad3170 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2706,6 +2706,9 @@ namespace ts { case SyntaxKind.NonNullExpression: node = parent; break; + case SyntaxKind.SpreadAssignment: + node = parent.parent; + break; case SyntaxKind.ShorthandPropertyAssignment: if ((parent as ShorthandPropertyAssignment).name !== node) { return AssignmentKind.None; @@ -4814,6 +4817,9 @@ namespace ts { && isLeftHandSideExpression(node.left); } + export function isLeftHandSideOfAssignment(node: Node) { + return isAssignmentExpression(node.parent) && node.parent.left === node; + } export function isDestructuringAssignment(node: Node): node is DestructuringAssignment { if (isAssignmentExpression(node, /*excludeCompoundAssignment*/ true)) { const kind = node.left.kind; diff --git a/tests/baselines/reference/privateWriteOnlyAccessorRead.errors.txt b/tests/baselines/reference/privateWriteOnlyAccessorRead.errors.txt new file mode 100644 index 0000000000000..47534c030719a --- /dev/null +++ b/tests/baselines/reference/privateWriteOnlyAccessorRead.errors.txt @@ -0,0 +1,55 @@ +tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts(8,17): error TS2806: Private accessor was defined without a getter. +tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts(11,5): error TS2806: Private accessor was defined without a getter. +tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts(16,13): error TS2806: Private accessor was defined without a getter. +tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts(18,17): error TS2806: Private accessor was defined without a getter. +tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts(21,18): error TS2806: Private accessor was defined without a getter. +tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts(25,9): error TS2806: Private accessor was defined without a getter. +tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts(26,12): error TS2806: Private accessor was defined without a getter. + + +==== tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts (7 errors) ==== + class Test { + set #value(v: { foo: { bar: number } }) {} + set #valueRest(v: number[]) {} + set #valueOne(v: number) {} + + m() { + const foo = { bar: 1 }; + console.log(this.#value); // error + ~~~~~~~~~~~ +!!! error TS2806: Private accessor was defined without a getter. + this.#value = { foo }; // ok + this.#value = { foo }; // ok + this.#value.foo = foo; // error + ~~~~~~~~~~~ +!!! error TS2806: Private accessor was defined without a getter. + + ({ o: this.#value } = { o: { foo } }); //ok + ({ ...this.#value } = { foo }); //ok + + ({ foo: this.#value.foo } = { foo }); //error + ~~~~~~~~~~~ +!!! error TS2806: Private accessor was defined without a getter. + ({ + foo: { ...this.#value.foo }, + ~~~~~~~~~~~ +!!! error TS2806: Private accessor was defined without a getter. + } = { foo }); //error + + let r = { o: this.#value }; //error + ~~~~~~~~~~~ +!!! error TS2806: Private accessor was defined without a getter. + + [this.#valueOne, ...this.#valueRest] = [1, 2, 3]; + let arr = [ + this.#valueOne, + ~~~~~~~~~~~~~~ +!!! error TS2806: Private accessor was defined without a getter. + ...this.#valueRest + ~~~~~~~~~~~~~~~ +!!! error TS2806: Private accessor was defined without a getter. + ]; + } + } + new Test().m(); + \ No newline at end of file diff --git a/tests/baselines/reference/privateWriteOnlyAccessorRead.js b/tests/baselines/reference/privateWriteOnlyAccessorRead.js new file mode 100644 index 0000000000000..0f4fce73b4130 --- /dev/null +++ b/tests/baselines/reference/privateWriteOnlyAccessorRead.js @@ -0,0 +1,87 @@ +//// [privateWriteOnlyAccessorRead.ts] +class Test { + set #value(v: { foo: { bar: number } }) {} + set #valueRest(v: number[]) {} + set #valueOne(v: number) {} + + m() { + const foo = { bar: 1 }; + console.log(this.#value); // error + this.#value = { foo }; // ok + this.#value = { foo }; // ok + this.#value.foo = foo; // error + + ({ o: this.#value } = { o: { foo } }); //ok + ({ ...this.#value } = { foo }); //ok + + ({ foo: this.#value.foo } = { foo }); //error + ({ + foo: { ...this.#value.foo }, + } = { foo }); //error + + let r = { o: this.#value }; //error + + [this.#valueOne, ...this.#valueRest] = [1, 2, 3]; + let arr = [ + this.#valueOne, + ...this.#valueRest + ]; + } +} +new Test().m(); + + +//// [privateWriteOnlyAccessorRead.js] +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 __rest = (this && this.__rest) || function (s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) + t[p[i]] = s[p[i]]; + } + return t; +}; +var _Test_instances, _Test_value_set, _Test_valueRest_set, _Test_valueOne_set; +class Test { + constructor() { + _Test_instances.add(this); + } + m() { + var _a, _b, _c; + const foo = { bar: 1 }; + console.log(__classPrivateFieldGet(this, _Test_instances, "a")); // error + __classPrivateFieldSet(// error + this, _Test_instances, { foo }, "a", _Test_value_set); // ok + __classPrivateFieldSet(// ok + this, _Test_instances, { foo }, "a", _Test_value_set); // ok + __classPrivateFieldGet(// ok + this, _Test_instances, "a").foo = foo; // error + (_a = this, { o: ({ set value(_d) { __classPrivateFieldSet(_a, _Test_instances, _d, "a", _Test_value_set); } }).value } = { o: { foo } }); //ok + (__classPrivateFieldGet(this, _Test_instances, "a") = __rest({ foo }, [])); //ok + ({ foo: __classPrivateFieldGet(this, _Test_instances, "a").foo } = { foo }); //error + ({ + foo: Object.assign({}, __classPrivateFieldGet(this, _Test_instances, "a").foo), + } = { foo }); //error + let r = { o: __classPrivateFieldGet(this, _Test_instances, "a") }; //error + _b = this, _c = this, [({ set value(_d) { __classPrivateFieldSet(_b, _Test_instances, _d, "a", _Test_valueOne_set); } }).value, ...({ set value(_d) { __classPrivateFieldSet(_c, _Test_instances, _d, "a", _Test_valueRest_set); } }).value] = [1, 2, 3]; + let arr = [ + __classPrivateFieldGet(this, _Test_instances, "a"), + ...__classPrivateFieldGet(this, _Test_instances, "a") + ]; + } +} +_Test_instances = new WeakSet(), _Test_value_set = function _Test_value_set(v) { }, _Test_valueRest_set = function _Test_valueRest_set(v) { }, _Test_valueOne_set = function _Test_valueOne_set(v) { }; +new Test().m(); diff --git a/tests/baselines/reference/privateWriteOnlyAccessorRead.symbols b/tests/baselines/reference/privateWriteOnlyAccessorRead.symbols new file mode 100644 index 0000000000000..a140e67fee604 --- /dev/null +++ b/tests/baselines/reference/privateWriteOnlyAccessorRead.symbols @@ -0,0 +1,111 @@ +=== tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts === +class Test { +>Test : Symbol(Test, Decl(privateWriteOnlyAccessorRead.ts, 0, 0)) + + set #value(v: { foo: { bar: number } }) {} +>#value : Symbol(Test.#value, Decl(privateWriteOnlyAccessorRead.ts, 0, 12)) +>v : Symbol(v, Decl(privateWriteOnlyAccessorRead.ts, 1, 13)) +>foo : Symbol(foo, Decl(privateWriteOnlyAccessorRead.ts, 1, 17)) +>bar : Symbol(bar, Decl(privateWriteOnlyAccessorRead.ts, 1, 24)) + + set #valueRest(v: number[]) {} +>#valueRest : Symbol(Test.#valueRest, Decl(privateWriteOnlyAccessorRead.ts, 1, 44)) +>v : Symbol(v, Decl(privateWriteOnlyAccessorRead.ts, 2, 17)) + + set #valueOne(v: number) {} +>#valueOne : Symbol(Test.#valueOne, Decl(privateWriteOnlyAccessorRead.ts, 2, 32)) +>v : Symbol(v, Decl(privateWriteOnlyAccessorRead.ts, 3, 16)) + + m() { +>m : Symbol(Test.m, Decl(privateWriteOnlyAccessorRead.ts, 3, 29)) + + const foo = { bar: 1 }; +>foo : Symbol(foo, Decl(privateWriteOnlyAccessorRead.ts, 6, 9)) +>bar : Symbol(bar, Decl(privateWriteOnlyAccessorRead.ts, 6, 17)) + + console.log(this.#value); // error +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>this.#value : Symbol(Test.#value, Decl(privateWriteOnlyAccessorRead.ts, 0, 12)) +>this : Symbol(Test, Decl(privateWriteOnlyAccessorRead.ts, 0, 0)) + + this.#value = { foo }; // ok +>this.#value : Symbol(Test.#value, Decl(privateWriteOnlyAccessorRead.ts, 0, 12)) +>this : Symbol(Test, Decl(privateWriteOnlyAccessorRead.ts, 0, 0)) +>foo : Symbol(foo, Decl(privateWriteOnlyAccessorRead.ts, 8, 19)) + + this.#value = { foo }; // ok +>this.#value : Symbol(Test.#value, Decl(privateWriteOnlyAccessorRead.ts, 0, 12)) +>this : Symbol(Test, Decl(privateWriteOnlyAccessorRead.ts, 0, 0)) +>foo : Symbol(foo, Decl(privateWriteOnlyAccessorRead.ts, 9, 19)) + + this.#value.foo = foo; // error +>this.#value.foo : Symbol(foo, Decl(privateWriteOnlyAccessorRead.ts, 1, 17)) +>this.#value : Symbol(Test.#value, Decl(privateWriteOnlyAccessorRead.ts, 0, 12)) +>this : Symbol(Test, Decl(privateWriteOnlyAccessorRead.ts, 0, 0)) +>foo : Symbol(foo, Decl(privateWriteOnlyAccessorRead.ts, 1, 17)) +>foo : Symbol(foo, Decl(privateWriteOnlyAccessorRead.ts, 6, 9)) + + ({ o: this.#value } = { o: { foo } }); //ok +>o : Symbol(o, Decl(privateWriteOnlyAccessorRead.ts, 12, 6)) +>this.#value : Symbol(Test.#value, Decl(privateWriteOnlyAccessorRead.ts, 0, 12)) +>this : Symbol(Test, Decl(privateWriteOnlyAccessorRead.ts, 0, 0)) +>o : Symbol(o, Decl(privateWriteOnlyAccessorRead.ts, 12, 27)) +>foo : Symbol(foo, Decl(privateWriteOnlyAccessorRead.ts, 12, 32)) + + ({ ...this.#value } = { foo }); //ok +>this.#value : Symbol(Test.#value, Decl(privateWriteOnlyAccessorRead.ts, 0, 12)) +>this : Symbol(Test, Decl(privateWriteOnlyAccessorRead.ts, 0, 0)) +>foo : Symbol(foo, Decl(privateWriteOnlyAccessorRead.ts, 13, 27)) + + ({ foo: this.#value.foo } = { foo }); //error +>foo : Symbol(foo, Decl(privateWriteOnlyAccessorRead.ts, 15, 6)) +>this.#value.foo : Symbol(foo, Decl(privateWriteOnlyAccessorRead.ts, 1, 17)) +>this.#value : Symbol(Test.#value, Decl(privateWriteOnlyAccessorRead.ts, 0, 12)) +>this : Symbol(Test, Decl(privateWriteOnlyAccessorRead.ts, 0, 0)) +>foo : Symbol(foo, Decl(privateWriteOnlyAccessorRead.ts, 1, 17)) +>foo : Symbol(foo, Decl(privateWriteOnlyAccessorRead.ts, 15, 33)) + + ({ + foo: { ...this.#value.foo }, +>foo : Symbol(foo, Decl(privateWriteOnlyAccessorRead.ts, 16, 6)) +>this.#value.foo : Symbol(foo, Decl(privateWriteOnlyAccessorRead.ts, 1, 17)) +>this.#value : Symbol(Test.#value, Decl(privateWriteOnlyAccessorRead.ts, 0, 12)) +>this : Symbol(Test, Decl(privateWriteOnlyAccessorRead.ts, 0, 0)) +>foo : Symbol(foo, Decl(privateWriteOnlyAccessorRead.ts, 1, 17)) + + } = { foo }); //error +>foo : Symbol(foo, Decl(privateWriteOnlyAccessorRead.ts, 18, 9)) + + let r = { o: this.#value }; //error +>r : Symbol(r, Decl(privateWriteOnlyAccessorRead.ts, 20, 7)) +>o : Symbol(o, Decl(privateWriteOnlyAccessorRead.ts, 20, 13)) +>this.#value : Symbol(Test.#value, Decl(privateWriteOnlyAccessorRead.ts, 0, 12)) +>this : Symbol(Test, Decl(privateWriteOnlyAccessorRead.ts, 0, 0)) + + [this.#valueOne, ...this.#valueRest] = [1, 2, 3]; +>this.#valueOne : Symbol(Test.#valueOne, Decl(privateWriteOnlyAccessorRead.ts, 2, 32)) +>this : Symbol(Test, Decl(privateWriteOnlyAccessorRead.ts, 0, 0)) +>this.#valueRest : Symbol(Test.#valueRest, Decl(privateWriteOnlyAccessorRead.ts, 1, 44)) +>this : Symbol(Test, Decl(privateWriteOnlyAccessorRead.ts, 0, 0)) + + let arr = [ +>arr : Symbol(arr, Decl(privateWriteOnlyAccessorRead.ts, 23, 7)) + + this.#valueOne, +>this.#valueOne : Symbol(Test.#valueOne, Decl(privateWriteOnlyAccessorRead.ts, 2, 32)) +>this : Symbol(Test, Decl(privateWriteOnlyAccessorRead.ts, 0, 0)) + + ...this.#valueRest +>this.#valueRest : Symbol(Test.#valueRest, Decl(privateWriteOnlyAccessorRead.ts, 1, 44)) +>this : Symbol(Test, Decl(privateWriteOnlyAccessorRead.ts, 0, 0)) + + ]; + } +} +new Test().m(); +>new Test().m : Symbol(Test.m, Decl(privateWriteOnlyAccessorRead.ts, 3, 29)) +>Test : Symbol(Test, Decl(privateWriteOnlyAccessorRead.ts, 0, 0)) +>m : Symbol(Test.m, Decl(privateWriteOnlyAccessorRead.ts, 3, 29)) + diff --git a/tests/baselines/reference/privateWriteOnlyAccessorRead.types b/tests/baselines/reference/privateWriteOnlyAccessorRead.types new file mode 100644 index 0000000000000..cb2b1d22f9668 --- /dev/null +++ b/tests/baselines/reference/privateWriteOnlyAccessorRead.types @@ -0,0 +1,150 @@ +=== tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts === +class Test { +>Test : Test + + set #value(v: { foo: { bar: number } }) {} +>#value : { foo: { bar: number;}; } +>v : { foo: { bar: number;}; } +>foo : { bar: number; } +>bar : number + + set #valueRest(v: number[]) {} +>#valueRest : number[] +>v : number[] + + set #valueOne(v: number) {} +>#valueOne : number +>v : number + + m() { +>m : () => void + + const foo = { bar: 1 }; +>foo : { bar: number; } +>{ bar: 1 } : { bar: number; } +>bar : number +>1 : 1 + + console.log(this.#value); // error +>console.log(this.#value) : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>this.#value : { foo: { bar: number; }; } +>this : this + + this.#value = { foo }; // ok +>this.#value = { foo } : { foo: { bar: number; }; } +>this.#value : { foo: { bar: number; }; } +>this : this +>{ foo } : { foo: { bar: number; }; } +>foo : { bar: number; } + + this.#value = { foo }; // ok +>this.#value = { foo } : { foo: { bar: number; }; } +>this.#value : { foo: { bar: number; }; } +>this : this +>{ foo } : { foo: { bar: number; }; } +>foo : { bar: number; } + + this.#value.foo = foo; // error +>this.#value.foo = foo : { bar: number; } +>this.#value.foo : { bar: number; } +>this.#value : { foo: { bar: number; }; } +>this : this +>foo : { bar: number; } +>foo : { bar: number; } + + ({ o: this.#value } = { o: { foo } }); //ok +>({ o: this.#value } = { o: { foo } }) : { o: { foo: { bar: number; }; }; } +>{ o: this.#value } = { o: { foo } } : { o: { foo: { bar: number; }; }; } +>{ o: this.#value } : { o: { foo: { bar: number; }; }; } +>o : { foo: { bar: number; }; } +>this.#value : { foo: { bar: number; }; } +>this : this +>{ o: { foo } } : { o: { foo: { bar: number; }; }; } +>o : { foo: { bar: number; }; } +>{ foo } : { foo: { bar: number; }; } +>foo : { bar: number; } + + ({ ...this.#value } = { foo }); //ok +>({ ...this.#value } = { foo }) : { foo: { bar: number; }; } +>{ ...this.#value } = { foo } : { foo: { bar: number; }; } +>{ ...this.#value } : { foo: { bar: number; }; } +>this.#value : { foo: { bar: number; }; } +>this : this +>{ foo } : { foo: { bar: number; }; } +>foo : { bar: number; } + + ({ foo: this.#value.foo } = { foo }); //error +>({ foo: this.#value.foo } = { foo }) : { foo: { bar: number; }; } +>{ foo: this.#value.foo } = { foo } : { foo: { bar: number; }; } +>{ foo: this.#value.foo } : { foo: { bar: number; }; } +>foo : { bar: number; } +>this.#value.foo : { bar: number; } +>this.#value : { foo: { bar: number; }; } +>this : this +>foo : { bar: number; } +>{ foo } : { foo: { bar: number; }; } +>foo : { bar: number; } + + ({ +>({ foo: { ...this.#value.foo }, } = { foo }) : { foo: { bar: number; }; } +>{ foo: { ...this.#value.foo }, } = { foo } : { foo: { bar: number; }; } +>{ foo: { ...this.#value.foo }, } : { foo: { bar: number; }; } + + foo: { ...this.#value.foo }, +>foo : { bar: number; } +>{ ...this.#value.foo } : { bar: number; } +>this.#value.foo : { bar: number; } +>this.#value : { foo: { bar: number; }; } +>this : this +>foo : { bar: number; } + + } = { foo }); //error +>{ foo } : { foo: { bar: number; }; } +>foo : { bar: number; } + + let r = { o: this.#value }; //error +>r : { o: { foo: { bar: number; }; }; } +>{ o: this.#value } : { o: { foo: { bar: number; }; }; } +>o : { foo: { bar: number; }; } +>this.#value : { foo: { bar: number; }; } +>this : this + + [this.#valueOne, ...this.#valueRest] = [1, 2, 3]; +>[this.#valueOne, ...this.#valueRest] = [1, 2, 3] : [number, number, number] +>[this.#valueOne, ...this.#valueRest] : [number, ...number[]] +>this.#valueOne : number +>this : this +>...this.#valueRest : number +>this.#valueRest : number[] +>this : this +>[1, 2, 3] : [number, number, number] +>1 : 1 +>2 : 2 +>3 : 3 + + let arr = [ +>arr : number[] +>[ this.#valueOne, ...this.#valueRest ] : number[] + + this.#valueOne, +>this.#valueOne : number +>this : this + + ...this.#valueRest +>...this.#valueRest : number +>this.#valueRest : number[] +>this : this + + ]; + } +} +new Test().m(); +>new Test().m() : void +>new Test().m : () => void +>new Test() : Test +>Test : typeof Test +>m : () => void + diff --git a/tests/baselines/reference/restPropertyWithBindingPattern.types b/tests/baselines/reference/restPropertyWithBindingPattern.types index b128042fb5b49..988d9b3c7afdc 100644 --- a/tests/baselines/reference/restPropertyWithBindingPattern.types +++ b/tests/baselines/reference/restPropertyWithBindingPattern.types @@ -17,15 +17,15 @@ ({...[]} = {}); >({...[]} = {}) : {} >{...[]} = {} : {} ->{...[]} : { [n: number]: undefined; length: number; toString(): string; toLocaleString(): string; pop(): undefined; push(...items: undefined[]): number; concat(...items: ConcatArray[]): undefined[]; concat(...items: ConcatArray[]): undefined[]; join(separator?: string): string; reverse(): undefined[]; shift(): undefined; slice(start?: number, end?: number): undefined[]; sort(compareFn?: (a: undefined, b: undefined) => number): undefined[]; splice(start: number, deleteCount?: number): undefined[]; splice(start: number, deleteCount: number, ...items: undefined[]): undefined[]; unshift(...items: undefined[]): number; indexOf(searchElement: undefined, fromIndex?: number): number; lastIndexOf(searchElement: undefined, fromIndex?: number): number; every(predicate: (value: undefined, index: number, array: undefined[]) => value is S, thisArg?: any): this is S[]; every(predicate: (value: undefined, index: number, array: undefined[]) => unknown, thisArg?: any): boolean; some(predicate: (value: undefined, index: number, array: undefined[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: undefined, index: number, array: undefined[]) => void, thisArg?: any): void; map(callbackfn: (value: undefined, index: number, array: undefined[]) => U, thisArg?: any): U[]; filter(predicate: (value: undefined, index: number, array: undefined[]) => value is S, thisArg?: any): S[]; filter(predicate: (value: undefined, index: number, array: undefined[]) => unknown, thisArg?: any): undefined[]; reduce(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined): undefined; reduce(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined, initialValue: undefined): undefined; reduce(callbackfn: (previousValue: U, currentValue: undefined, currentIndex: number, array: undefined[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined): undefined; reduceRight(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined, initialValue: undefined): undefined; reduceRight(callbackfn: (previousValue: U, currentValue: undefined, currentIndex: number, array: undefined[]) => U, initialValue: U): U; } ->[] : undefined[] +>{...[]} : { [n: number]: never; length: 0; toString(): string; toLocaleString(): string; pop(): never; push(...items: never[]): number; concat(...items: ConcatArray[]): never[]; concat(...items: ConcatArray[]): never[]; join(separator?: string): string; reverse(): never[]; shift(): never; slice(start?: number, end?: number): never[]; sort(compareFn?: (a: never, b: never) => number): []; splice(start: number, deleteCount?: number): never[]; splice(start: number, deleteCount: number, ...items: never[]): never[]; unshift(...items: never[]): number; indexOf(searchElement: never, fromIndex?: number): number; lastIndexOf(searchElement: never, fromIndex?: number): number; every(predicate: (value: never, index: number, array: never[]) => value is S, thisArg?: any): this is S[]; every(predicate: (value: never, index: number, array: never[]) => unknown, thisArg?: any): boolean; some(predicate: (value: never, index: number, array: never[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: never, index: number, array: never[]) => void, thisArg?: any): void; map(callbackfn: (value: never, index: number, array: never[]) => U, thisArg?: any): U[]; filter(predicate: (value: never, index: number, array: never[]) => value is S, thisArg?: any): S[]; filter(predicate: (value: never, index: number, array: never[]) => unknown, thisArg?: any): never[]; reduce(callbackfn: (previousValue: never, currentValue: never, currentIndex: number, array: never[]) => never): never; reduce(callbackfn: (previousValue: never, currentValue: never, currentIndex: number, array: never[]) => never, initialValue: never): never; reduce(callbackfn: (previousValue: U, currentValue: never, currentIndex: number, array: never[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: never, currentValue: never, currentIndex: number, array: never[]) => never): never; reduceRight(callbackfn: (previousValue: never, currentValue: never, currentIndex: number, array: never[]) => never, initialValue: never): never; reduceRight(callbackfn: (previousValue: U, currentValue: never, currentIndex: number, array: never[]) => U, initialValue: U): U; } +>[] : [] >{} : {} ({...([])} = {}); >({...([])} = {}) : {} >{...([])} = {} : {} ->{...([])} : { [n: number]: undefined; length: number; toString(): string; toLocaleString(): string; pop(): undefined; push(...items: undefined[]): number; concat(...items: ConcatArray[]): undefined[]; concat(...items: ConcatArray[]): undefined[]; join(separator?: string): string; reverse(): undefined[]; shift(): undefined; slice(start?: number, end?: number): undefined[]; sort(compareFn?: (a: undefined, b: undefined) => number): undefined[]; splice(start: number, deleteCount?: number): undefined[]; splice(start: number, deleteCount: number, ...items: undefined[]): undefined[]; unshift(...items: undefined[]): number; indexOf(searchElement: undefined, fromIndex?: number): number; lastIndexOf(searchElement: undefined, fromIndex?: number): number; every(predicate: (value: undefined, index: number, array: undefined[]) => value is S, thisArg?: any): this is S[]; every(predicate: (value: undefined, index: number, array: undefined[]) => unknown, thisArg?: any): boolean; some(predicate: (value: undefined, index: number, array: undefined[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: undefined, index: number, array: undefined[]) => void, thisArg?: any): void; map(callbackfn: (value: undefined, index: number, array: undefined[]) => U, thisArg?: any): U[]; filter(predicate: (value: undefined, index: number, array: undefined[]) => value is S, thisArg?: any): S[]; filter(predicate: (value: undefined, index: number, array: undefined[]) => unknown, thisArg?: any): undefined[]; reduce(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined): undefined; reduce(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined, initialValue: undefined): undefined; reduce(callbackfn: (previousValue: U, currentValue: undefined, currentIndex: number, array: undefined[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined): undefined; reduceRight(callbackfn: (previousValue: undefined, currentValue: undefined, currentIndex: number, array: undefined[]) => undefined, initialValue: undefined): undefined; reduceRight(callbackfn: (previousValue: U, currentValue: undefined, currentIndex: number, array: undefined[]) => U, initialValue: U): U; } ->([]) : undefined[] ->[] : undefined[] +>{...([])} : { [n: number]: never; length: 0; toString(): string; toLocaleString(): string; pop(): never; push(...items: never[]): number; concat(...items: ConcatArray[]): never[]; concat(...items: ConcatArray[]): never[]; join(separator?: string): string; reverse(): never[]; shift(): never; slice(start?: number, end?: number): never[]; sort(compareFn?: (a: never, b: never) => number): []; splice(start: number, deleteCount?: number): never[]; splice(start: number, deleteCount: number, ...items: never[]): never[]; unshift(...items: never[]): number; indexOf(searchElement: never, fromIndex?: number): number; lastIndexOf(searchElement: never, fromIndex?: number): number; every(predicate: (value: never, index: number, array: never[]) => value is S, thisArg?: any): this is S[]; every(predicate: (value: never, index: number, array: never[]) => unknown, thisArg?: any): boolean; some(predicate: (value: never, index: number, array: never[]) => unknown, thisArg?: any): boolean; forEach(callbackfn: (value: never, index: number, array: never[]) => void, thisArg?: any): void; map(callbackfn: (value: never, index: number, array: never[]) => U, thisArg?: any): U[]; filter(predicate: (value: never, index: number, array: never[]) => value is S, thisArg?: any): S[]; filter(predicate: (value: never, index: number, array: never[]) => unknown, thisArg?: any): never[]; reduce(callbackfn: (previousValue: never, currentValue: never, currentIndex: number, array: never[]) => never): never; reduce(callbackfn: (previousValue: never, currentValue: never, currentIndex: number, array: never[]) => never, initialValue: never): never; reduce(callbackfn: (previousValue: U, currentValue: never, currentIndex: number, array: never[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: never, currentValue: never, currentIndex: number, array: never[]) => never): never; reduceRight(callbackfn: (previousValue: never, currentValue: never, currentIndex: number, array: never[]) => never, initialValue: never): never; reduceRight(callbackfn: (previousValue: U, currentValue: never, currentIndex: number, array: never[]) => U, initialValue: U): U; } +>([]) : [] +>[] : [] >{} : {} diff --git a/tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts b/tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts new file mode 100644 index 0000000000000..ab71685f053d2 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts @@ -0,0 +1,31 @@ +// @target: es2015 +class Test { + set #value(v: { foo: { bar: number } }) {} + set #valueRest(v: number[]) {} + set #valueOne(v: number) {} + + m() { + const foo = { bar: 1 }; + console.log(this.#value); // error + this.#value = { foo }; // ok + this.#value = { foo }; // ok + this.#value.foo = foo; // error + + ({ o: this.#value } = { o: { foo } }); //ok + ({ ...this.#value } = { foo }); //ok + + ({ foo: this.#value.foo } = { foo }); //error + ({ + foo: { ...this.#value.foo }, + } = { foo }); //error + + let r = { o: this.#value }; //error + + [this.#valueOne, ...this.#valueRest] = [1, 2, 3]; + let arr = [ + this.#valueOne, + ...this.#valueRest + ]; + } +} +new Test().m();