From 7dded409e4b8408c047b342d9877c7350c201eaa Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Tue, 7 Aug 2018 17:16:06 -0700 Subject: [PATCH] Don't include class getter in spread type --- src/compiler/checker.ts | 24 ++- tests/baselines/reference/objectRest.types | 2 +- .../reference/spreadMethods.errors.txt | 37 +++- tests/baselines/reference/spreadMethods.js | 70 ++++---- .../baselines/reference/spreadMethods.symbols | 161 +++++++++++------- tests/baselines/reference/spreadMethods.types | 101 ++++++++--- .../conformance/types/spread/spreadMethods.ts | 27 ++- 7 files changed, 282 insertions(+), 140 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 71fd9ca42e774..0c1d419766e4e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4461,10 +4461,7 @@ namespace ts { names.set(getTextOfPropertyName(name), true); } for (const prop of getPropertiesOfType(source)) { - const inNamesToRemove = names.has(prop.escapedName); - const isPrivate = getDeclarationModifierFlagsFromSymbol(prop) & (ModifierFlags.Private | ModifierFlags.Protected); - const isSetOnlyAccessor = prop.flags & SymbolFlags.SetAccessor && !(prop.flags & SymbolFlags.GetAccessor); - if (!inNamesToRemove && !isPrivate && !isClassMethod(prop) && !isSetOnlyAccessor) { + if (!names.has(prop.escapedName) && !(getDeclarationModifierFlagsFromSymbol(prop) & (ModifierFlags.Private | ModifierFlags.Protected)) && isSpreadableProperty(prop)) { members.set(prop.escapedName, getNonReadonlySymbol(prop)); } } @@ -9646,20 +9643,16 @@ namespace ts { } for (const rightProp of getPropertiesOfType(right)) { - // we approximate own properties as non-methods plus methods that are inside the object literal - const isSetterWithoutGetter = rightProp.flags & SymbolFlags.SetAccessor && !(rightProp.flags & SymbolFlags.GetAccessor); if (getDeclarationModifierFlagsFromSymbol(rightProp) & (ModifierFlags.Private | ModifierFlags.Protected)) { skippedPrivateMembers.set(rightProp.escapedName, true); } - else if (!isClassMethod(rightProp) && !isSetterWithoutGetter) { + else if (isSpreadableProperty(rightProp)) { members.set(rightProp.escapedName, getNonReadonlySymbol(rightProp)); } } for (const leftProp of getPropertiesOfType(left)) { - if (leftProp.flags & SymbolFlags.SetAccessor && !(leftProp.flags & SymbolFlags.GetAccessor) - || skippedPrivateMembers.has(leftProp.escapedName) - || isClassMethod(leftProp)) { + if (skippedPrivateMembers.has(leftProp.escapedName) || !isSpreadableProperty(leftProp)) { continue; } if (members.has(leftProp.escapedName)) { @@ -9694,6 +9687,13 @@ namespace ts { return spread; } + function isSpreadableProperty(prop: Symbol): boolean { + // We approximate own properties as non-methods plus methods that are inside the object literal + return prop.flags & (SymbolFlags.Method | SymbolFlags.GetAccessor) + ? !prop.declarations.some(decl => isClassLike(decl.parent)) + : !(prop.flags & SymbolFlags.SetAccessor); // Setter without getter is not spreadable + } + function getNonReadonlySymbol(prop: Symbol) { if (!isReadonlySymbol(prop)) { return prop; @@ -9714,10 +9714,6 @@ namespace ts { return index; } - function isClassMethod(prop: Symbol) { - return prop.flags & SymbolFlags.Method && find(prop.declarations, decl => isClassLike(decl.parent)); - } - function createLiteralType(flags: TypeFlags, value: string | number, symbol: Symbol | undefined) { const type = createType(flags); type.symbol = symbol!; diff --git a/tests/baselines/reference/objectRest.types b/tests/baselines/reference/objectRest.types index b096b1768f5db..cb50daf9c4b0a 100644 --- a/tests/baselines/reference/objectRest.types +++ b/tests/baselines/reference/objectRest.types @@ -175,7 +175,7 @@ var removable = new Removable(); var { removed, ...removableRest } = removable; >removed : string ->removableRest : { both: number; remainder: string; } +>removableRest : { remainder: string; } >removable : Removable var i: I = removable; diff --git a/tests/baselines/reference/spreadMethods.errors.txt b/tests/baselines/reference/spreadMethods.errors.txt index b2b3491ba7936..1dfef327e4763 100644 --- a/tests/baselines/reference/spreadMethods.errors.txt +++ b/tests/baselines/reference/spreadMethods.errors.txt @@ -1,10 +1,21 @@ -tests/cases/conformance/types/spread/spreadMethods.ts(7,4): error TS2339: Property 'm' does not exist on type '{ p: number; }'. -tests/cases/conformance/types/spread/spreadMethods.ts(9,5): error TS2339: Property 'm' does not exist on type '{ p: number; }'. +tests/cases/conformance/types/spread/spreadMethods.ts(16,4): error TS2339: Property 'm' does not exist on type '{ p: number; }'. +tests/cases/conformance/types/spread/spreadMethods.ts(17,4): error TS2339: Property 'g' does not exist on type '{ p: number; }'. +tests/cases/conformance/types/spread/spreadMethods.ts(19,5): error TS2339: Property 'm' does not exist on type '{ p: number; }'. +tests/cases/conformance/types/spread/spreadMethods.ts(20,5): error TS2339: Property 'g' does not exist on type '{ p: number; }'. -==== tests/cases/conformance/types/spread/spreadMethods.ts (2 errors) ==== - class K { p = 12; m() { } } - interface I { p: number, m(): void } +==== tests/cases/conformance/types/spread/spreadMethods.ts (4 errors) ==== + class K { + p = 12; + m() { } + get g() { return 0; } + } + interface I { + p: number; + m(): void; + readonly g: number; + } + let k = new K() let sk = { ...k }; let ssk = { ...k, ...k }; @@ -12,22 +23,34 @@ tests/cases/conformance/types/spread/spreadMethods.ts(9,5): error TS2339: Proper sk.m(); // error ~ !!! error TS2339: Property 'm' does not exist on type '{ p: number; }'. + sk.g; // error + ~ +!!! error TS2339: Property 'g' does not exist on type '{ p: number; }'. ssk.p; ssk.m(); // error ~ !!! error TS2339: Property 'm' does not exist on type '{ p: number; }'. - let i: I = { p: 12, m() { } }; + ssk.g; // error + ~ +!!! error TS2339: Property 'g' does not exist on type '{ p: number; }'. + + let i: I = { p: 12, m() { }, get g() { return 0; } }; let si = { ...i }; let ssi = { ...i, ...i }; si.p; si.m(); // ok + si.g; // ok ssi.p; ssi.m(); // ok - let o = { p: 12, m() { } }; + ssi.g; // ok + + let o = { p: 12, m() { }, get g() { return 0; } }; let so = { ...o }; let sso = { ...o, ...o }; so.p; so.m(); // ok + so.g; // ok sso.p; sso.m(); // ok + sso.g; // ok \ No newline at end of file diff --git a/tests/baselines/reference/spreadMethods.js b/tests/baselines/reference/spreadMethods.js index e5e5284516a7a..b35619361f1f0 100644 --- a/tests/baselines/reference/spreadMethods.js +++ b/tests/baselines/reference/spreadMethods.js @@ -1,66 +1,78 @@ //// [spreadMethods.ts] -class K { p = 12; m() { } } -interface I { p: number, m(): void } +class K { + p = 12; + m() { } + get g() { return 0; } +} +interface I { + p: number; + m(): void; + readonly g: number; +} + let k = new K() let sk = { ...k }; let ssk = { ...k, ...k }; sk.p; sk.m(); // error +sk.g; // error ssk.p; ssk.m(); // error -let i: I = { p: 12, m() { } }; +ssk.g; // error + +let i: I = { p: 12, m() { }, get g() { return 0; } }; let si = { ...i }; let ssi = { ...i, ...i }; si.p; si.m(); // ok +si.g; // ok ssi.p; ssi.m(); // ok -let o = { p: 12, m() { } }; +ssi.g; // ok + +let o = { p: 12, m() { }, get g() { return 0; } }; let so = { ...o }; let sso = { ...o, ...o }; so.p; so.m(); // ok +so.g; // ok sso.p; sso.m(); // ok +sso.g; // ok //// [spreadMethods.js] -var __assign = (this && this.__assign) || function () { - __assign = Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); -}; -var K = /** @class */ (function () { - function K() { +class K { + constructor() { this.p = 12; } - K.prototype.m = function () { }; - return K; -}()); -var k = new K(); -var sk = __assign({}, k); -var ssk = __assign({}, k, k); + m() { } + get g() { return 0; } +} +let k = new K(); +let sk = { ...k }; +let ssk = { ...k, ...k }; sk.p; sk.m(); // error +sk.g; // error ssk.p; ssk.m(); // error -var i = { p: 12, m: function () { } }; -var si = __assign({}, i); -var ssi = __assign({}, i, i); +ssk.g; // error +let i = { p: 12, m() { }, get g() { return 0; } }; +let si = { ...i }; +let ssi = { ...i, ...i }; si.p; si.m(); // ok +si.g; // ok ssi.p; ssi.m(); // ok -var o = { p: 12, m: function () { } }; -var so = __assign({}, o); -var sso = __assign({}, o, o); +ssi.g; // ok +let o = { p: 12, m() { }, get g() { return 0; } }; +let so = { ...o }; +let sso = { ...o, ...o }; so.p; so.m(); // ok +so.g; // ok sso.p; sso.m(); // ok +sso.g; // ok diff --git a/tests/baselines/reference/spreadMethods.symbols b/tests/baselines/reference/spreadMethods.symbols index 64db9dcdfc9af..7b6090f3c665c 100644 --- a/tests/baselines/reference/spreadMethods.symbols +++ b/tests/baselines/reference/spreadMethods.symbols @@ -1,109 +1,152 @@ === tests/cases/conformance/types/spread/spreadMethods.ts === -class K { p = 12; m() { } } +class K { >K : Symbol(K, Decl(spreadMethods.ts, 0, 0)) + + p = 12; >p : Symbol(K.p, Decl(spreadMethods.ts, 0, 9)) ->m : Symbol(K.m, Decl(spreadMethods.ts, 0, 17)) -interface I { p: number, m(): void } ->I : Symbol(I, Decl(spreadMethods.ts, 0, 27)) ->p : Symbol(I.p, Decl(spreadMethods.ts, 1, 13)) ->m : Symbol(I.m, Decl(spreadMethods.ts, 1, 24)) + m() { } +>m : Symbol(K.m, Decl(spreadMethods.ts, 1, 11)) + + get g() { return 0; } +>g : Symbol(K.g, Decl(spreadMethods.ts, 2, 11)) +} +interface I { +>I : Symbol(I, Decl(spreadMethods.ts, 4, 1)) + + p: number; +>p : Symbol(I.p, Decl(spreadMethods.ts, 5, 13)) + + m(): void; +>m : Symbol(I.m, Decl(spreadMethods.ts, 6, 14)) + + readonly g: number; +>g : Symbol(I.g, Decl(spreadMethods.ts, 7, 14)) +} let k = new K() ->k : Symbol(k, Decl(spreadMethods.ts, 2, 3)) +>k : Symbol(k, Decl(spreadMethods.ts, 11, 3)) >K : Symbol(K, Decl(spreadMethods.ts, 0, 0)) let sk = { ...k }; ->sk : Symbol(sk, Decl(spreadMethods.ts, 3, 3)) ->k : Symbol(k, Decl(spreadMethods.ts, 2, 3)) +>sk : Symbol(sk, Decl(spreadMethods.ts, 12, 3)) +>k : Symbol(k, Decl(spreadMethods.ts, 11, 3)) let ssk = { ...k, ...k }; ->ssk : Symbol(ssk, Decl(spreadMethods.ts, 4, 3)) ->k : Symbol(k, Decl(spreadMethods.ts, 2, 3)) ->k : Symbol(k, Decl(spreadMethods.ts, 2, 3)) +>ssk : Symbol(ssk, Decl(spreadMethods.ts, 13, 3)) +>k : Symbol(k, Decl(spreadMethods.ts, 11, 3)) +>k : Symbol(k, Decl(spreadMethods.ts, 11, 3)) sk.p; >sk.p : Symbol(K.p, Decl(spreadMethods.ts, 0, 9)) ->sk : Symbol(sk, Decl(spreadMethods.ts, 3, 3)) +>sk : Symbol(sk, Decl(spreadMethods.ts, 12, 3)) >p : Symbol(K.p, Decl(spreadMethods.ts, 0, 9)) sk.m(); // error ->sk : Symbol(sk, Decl(spreadMethods.ts, 3, 3)) +>sk : Symbol(sk, Decl(spreadMethods.ts, 12, 3)) + +sk.g; // error +>sk : Symbol(sk, Decl(spreadMethods.ts, 12, 3)) ssk.p; >ssk.p : Symbol(K.p, Decl(spreadMethods.ts, 0, 9)) ->ssk : Symbol(ssk, Decl(spreadMethods.ts, 4, 3)) +>ssk : Symbol(ssk, Decl(spreadMethods.ts, 13, 3)) >p : Symbol(K.p, Decl(spreadMethods.ts, 0, 9)) ssk.m(); // error ->ssk : Symbol(ssk, Decl(spreadMethods.ts, 4, 3)) +>ssk : Symbol(ssk, Decl(spreadMethods.ts, 13, 3)) + +ssk.g; // error +>ssk : Symbol(ssk, Decl(spreadMethods.ts, 13, 3)) -let i: I = { p: 12, m() { } }; ->i : Symbol(i, Decl(spreadMethods.ts, 9, 3)) ->I : Symbol(I, Decl(spreadMethods.ts, 0, 27)) ->p : Symbol(p, Decl(spreadMethods.ts, 9, 12)) ->m : Symbol(m, Decl(spreadMethods.ts, 9, 19)) +let i: I = { p: 12, m() { }, get g() { return 0; } }; +>i : Symbol(i, Decl(spreadMethods.ts, 21, 3)) +>I : Symbol(I, Decl(spreadMethods.ts, 4, 1)) +>p : Symbol(p, Decl(spreadMethods.ts, 21, 12)) +>m : Symbol(m, Decl(spreadMethods.ts, 21, 19)) +>g : Symbol(g, Decl(spreadMethods.ts, 21, 28)) let si = { ...i }; ->si : Symbol(si, Decl(spreadMethods.ts, 10, 3)) ->i : Symbol(i, Decl(spreadMethods.ts, 9, 3)) +>si : Symbol(si, Decl(spreadMethods.ts, 22, 3)) +>i : Symbol(i, Decl(spreadMethods.ts, 21, 3)) let ssi = { ...i, ...i }; ->ssi : Symbol(ssi, Decl(spreadMethods.ts, 11, 3)) ->i : Symbol(i, Decl(spreadMethods.ts, 9, 3)) ->i : Symbol(i, Decl(spreadMethods.ts, 9, 3)) +>ssi : Symbol(ssi, Decl(spreadMethods.ts, 23, 3)) +>i : Symbol(i, Decl(spreadMethods.ts, 21, 3)) +>i : Symbol(i, Decl(spreadMethods.ts, 21, 3)) si.p; ->si.p : Symbol(I.p, Decl(spreadMethods.ts, 1, 13)) ->si : Symbol(si, Decl(spreadMethods.ts, 10, 3)) ->p : Symbol(I.p, Decl(spreadMethods.ts, 1, 13)) +>si.p : Symbol(I.p, Decl(spreadMethods.ts, 5, 13)) +>si : Symbol(si, Decl(spreadMethods.ts, 22, 3)) +>p : Symbol(I.p, Decl(spreadMethods.ts, 5, 13)) si.m(); // ok ->si.m : Symbol(I.m, Decl(spreadMethods.ts, 1, 24)) ->si : Symbol(si, Decl(spreadMethods.ts, 10, 3)) ->m : Symbol(I.m, Decl(spreadMethods.ts, 1, 24)) +>si.m : Symbol(I.m, Decl(spreadMethods.ts, 6, 14)) +>si : Symbol(si, Decl(spreadMethods.ts, 22, 3)) +>m : Symbol(I.m, Decl(spreadMethods.ts, 6, 14)) + +si.g; // ok +>si.g : Symbol(g, Decl(spreadMethods.ts, 7, 14)) +>si : Symbol(si, Decl(spreadMethods.ts, 22, 3)) +>g : Symbol(g, Decl(spreadMethods.ts, 7, 14)) ssi.p; ->ssi.p : Symbol(I.p, Decl(spreadMethods.ts, 1, 13)) ->ssi : Symbol(ssi, Decl(spreadMethods.ts, 11, 3)) ->p : Symbol(I.p, Decl(spreadMethods.ts, 1, 13)) +>ssi.p : Symbol(I.p, Decl(spreadMethods.ts, 5, 13)) +>ssi : Symbol(ssi, Decl(spreadMethods.ts, 23, 3)) +>p : Symbol(I.p, Decl(spreadMethods.ts, 5, 13)) ssi.m(); // ok ->ssi.m : Symbol(I.m, Decl(spreadMethods.ts, 1, 24)) ->ssi : Symbol(ssi, Decl(spreadMethods.ts, 11, 3)) ->m : Symbol(I.m, Decl(spreadMethods.ts, 1, 24)) +>ssi.m : Symbol(I.m, Decl(spreadMethods.ts, 6, 14)) +>ssi : Symbol(ssi, Decl(spreadMethods.ts, 23, 3)) +>m : Symbol(I.m, Decl(spreadMethods.ts, 6, 14)) -let o = { p: 12, m() { } }; ->o : Symbol(o, Decl(spreadMethods.ts, 16, 3)) ->p : Symbol(p, Decl(spreadMethods.ts, 16, 9)) ->m : Symbol(m, Decl(spreadMethods.ts, 16, 16)) +ssi.g; // ok +>ssi.g : Symbol(g, Decl(spreadMethods.ts, 7, 14)) +>ssi : Symbol(ssi, Decl(spreadMethods.ts, 23, 3)) +>g : Symbol(g, Decl(spreadMethods.ts, 7, 14)) + +let o = { p: 12, m() { }, get g() { return 0; } }; +>o : Symbol(o, Decl(spreadMethods.ts, 31, 3)) +>p : Symbol(p, Decl(spreadMethods.ts, 31, 9)) +>m : Symbol(m, Decl(spreadMethods.ts, 31, 16)) +>g : Symbol(g, Decl(spreadMethods.ts, 31, 25)) let so = { ...o }; ->so : Symbol(so, Decl(spreadMethods.ts, 17, 3)) ->o : Symbol(o, Decl(spreadMethods.ts, 16, 3)) +>so : Symbol(so, Decl(spreadMethods.ts, 32, 3)) +>o : Symbol(o, Decl(spreadMethods.ts, 31, 3)) let sso = { ...o, ...o }; ->sso : Symbol(sso, Decl(spreadMethods.ts, 18, 3)) ->o : Symbol(o, Decl(spreadMethods.ts, 16, 3)) ->o : Symbol(o, Decl(spreadMethods.ts, 16, 3)) +>sso : Symbol(sso, Decl(spreadMethods.ts, 33, 3)) +>o : Symbol(o, Decl(spreadMethods.ts, 31, 3)) +>o : Symbol(o, Decl(spreadMethods.ts, 31, 3)) so.p; ->so.p : Symbol(p, Decl(spreadMethods.ts, 16, 9)) ->so : Symbol(so, Decl(spreadMethods.ts, 17, 3)) ->p : Symbol(p, Decl(spreadMethods.ts, 16, 9)) +>so.p : Symbol(p, Decl(spreadMethods.ts, 31, 9)) +>so : Symbol(so, Decl(spreadMethods.ts, 32, 3)) +>p : Symbol(p, Decl(spreadMethods.ts, 31, 9)) so.m(); // ok ->so.m : Symbol(m, Decl(spreadMethods.ts, 16, 16)) ->so : Symbol(so, Decl(spreadMethods.ts, 17, 3)) ->m : Symbol(m, Decl(spreadMethods.ts, 16, 16)) +>so.m : Symbol(m, Decl(spreadMethods.ts, 31, 16)) +>so : Symbol(so, Decl(spreadMethods.ts, 32, 3)) +>m : Symbol(m, Decl(spreadMethods.ts, 31, 16)) + +so.g; // ok +>so.g : Symbol(g, Decl(spreadMethods.ts, 31, 25)) +>so : Symbol(so, Decl(spreadMethods.ts, 32, 3)) +>g : Symbol(g, Decl(spreadMethods.ts, 31, 25)) sso.p; ->sso.p : Symbol(p, Decl(spreadMethods.ts, 16, 9)) ->sso : Symbol(sso, Decl(spreadMethods.ts, 18, 3)) ->p : Symbol(p, Decl(spreadMethods.ts, 16, 9)) +>sso.p : Symbol(p, Decl(spreadMethods.ts, 31, 9)) +>sso : Symbol(sso, Decl(spreadMethods.ts, 33, 3)) +>p : Symbol(p, Decl(spreadMethods.ts, 31, 9)) sso.m(); // ok ->sso.m : Symbol(m, Decl(spreadMethods.ts, 16, 16)) ->sso : Symbol(sso, Decl(spreadMethods.ts, 18, 3)) ->m : Symbol(m, Decl(spreadMethods.ts, 16, 16)) +>sso.m : Symbol(m, Decl(spreadMethods.ts, 31, 16)) +>sso : Symbol(sso, Decl(spreadMethods.ts, 33, 3)) +>m : Symbol(m, Decl(spreadMethods.ts, 31, 16)) + +sso.g; // ok +>sso.g : Symbol(g, Decl(spreadMethods.ts, 31, 25)) +>sso : Symbol(sso, Decl(spreadMethods.ts, 33, 3)) +>g : Symbol(g, Decl(spreadMethods.ts, 31, 25)) diff --git a/tests/baselines/reference/spreadMethods.types b/tests/baselines/reference/spreadMethods.types index 189808dc95692..88a2c9c735301 100644 --- a/tests/baselines/reference/spreadMethods.types +++ b/tests/baselines/reference/spreadMethods.types @@ -1,14 +1,29 @@ === tests/cases/conformance/types/spread/spreadMethods.ts === -class K { p = 12; m() { } } +class K { >K : K + + p = 12; >p : number >12 : 12 + + m() { } >m : () => void -interface I { p: number, m(): void } + get g() { return 0; } +>g : number +>0 : 0 +} +interface I { + p: number; >p : number + + m(): void; >m : () => void + readonly g: number; +>g : number +} + let k = new K() >k : K >new K() : K @@ -36,6 +51,11 @@ sk.m(); // error >sk : { p: number; } >m : any +sk.g; // error +>sk.g : any +>sk : { p: number; } +>g : any + ssk.p; >ssk.p : number >ssk : { p: number; } @@ -47,83 +67,112 @@ ssk.m(); // error >ssk : { p: number; } >m : any -let i: I = { p: 12, m() { } }; +ssk.g; // error +>ssk.g : any +>ssk : { p: number; } +>g : any + +let i: I = { p: 12, m() { }, get g() { return 0; } }; >i : I ->{ p: 12, m() { } } : { p: number; m(): void; } +>{ p: 12, m() { }, get g() { return 0; } } : { p: number; m(): void; readonly g: number; } >p : number >12 : 12 >m : () => void +>g : number +>0 : 0 let si = { ...i }; ->si : { p: number; m(): void; } ->{ ...i } : { p: number; m(): void; } +>si : { p: number; m(): void; g: number; } +>{ ...i } : { p: number; m(): void; g: number; } >i : I let ssi = { ...i, ...i }; ->ssi : { p: number; m(): void; } ->{ ...i, ...i } : { p: number; m(): void; } +>ssi : { p: number; m(): void; g: number; } +>{ ...i, ...i } : { p: number; m(): void; g: number; } >i : I >i : I si.p; >si.p : number ->si : { p: number; m(): void; } +>si : { p: number; m(): void; g: number; } >p : number si.m(); // ok >si.m() : void >si.m : () => void ->si : { p: number; m(): void; } +>si : { p: number; m(): void; g: number; } >m : () => void +si.g; // ok +>si.g : number +>si : { p: number; m(): void; g: number; } +>g : number + ssi.p; >ssi.p : number ->ssi : { p: number; m(): void; } +>ssi : { p: number; m(): void; g: number; } >p : number ssi.m(); // ok >ssi.m() : void >ssi.m : () => void ->ssi : { p: number; m(): void; } +>ssi : { p: number; m(): void; g: number; } >m : () => void -let o = { p: 12, m() { } }; ->o : { p: number; m(): void; } ->{ p: 12, m() { } } : { p: number; m(): void; } +ssi.g; // ok +>ssi.g : number +>ssi : { p: number; m(): void; g: number; } +>g : number + +let o = { p: 12, m() { }, get g() { return 0; } }; +>o : { p: number; m(): void; readonly g: number; } +>{ p: 12, m() { }, get g() { return 0; } } : { p: number; m(): void; readonly g: number; } >p : number >12 : 12 >m : () => void +>g : number +>0 : 0 let so = { ...o }; ->so : { p: number; m(): void; } ->{ ...o } : { p: number; m(): void; } ->o : { p: number; m(): void; } +>so : { p: number; m(): void; g: number; } +>{ ...o } : { p: number; m(): void; g: number; } +>o : { p: number; m(): void; readonly g: number; } let sso = { ...o, ...o }; ->sso : { p: number; m(): void; } ->{ ...o, ...o } : { p: number; m(): void; } ->o : { p: number; m(): void; } ->o : { p: number; m(): void; } +>sso : { p: number; m(): void; g: number; } +>{ ...o, ...o } : { p: number; m(): void; g: number; } +>o : { p: number; m(): void; readonly g: number; } +>o : { p: number; m(): void; readonly g: number; } so.p; >so.p : number ->so : { p: number; m(): void; } +>so : { p: number; m(): void; g: number; } >p : number so.m(); // ok >so.m() : void >so.m : () => void ->so : { p: number; m(): void; } +>so : { p: number; m(): void; g: number; } >m : () => void +so.g; // ok +>so.g : number +>so : { p: number; m(): void; g: number; } +>g : number + sso.p; >sso.p : number ->sso : { p: number; m(): void; } +>sso : { p: number; m(): void; g: number; } >p : number sso.m(); // ok >sso.m() : void >sso.m : () => void ->sso : { p: number; m(): void; } +>sso : { p: number; m(): void; g: number; } >m : () => void +sso.g; // ok +>sso.g : number +>sso : { p: number; m(): void; g: number; } +>g : number + diff --git a/tests/cases/conformance/types/spread/spreadMethods.ts b/tests/cases/conformance/types/spread/spreadMethods.ts index 5d56265342484..10658d97972ef 100644 --- a/tests/cases/conformance/types/spread/spreadMethods.ts +++ b/tests/cases/conformance/types/spread/spreadMethods.ts @@ -1,23 +1,42 @@ -class K { p = 12; m() { } } -interface I { p: number, m(): void } +// @target: esnext + +class K { + p = 12; + m() { } + get g() { return 0; } +} +interface I { + p: number; + m(): void; + readonly g: number; +} + let k = new K() let sk = { ...k }; let ssk = { ...k, ...k }; sk.p; sk.m(); // error +sk.g; // error ssk.p; ssk.m(); // error -let i: I = { p: 12, m() { } }; +ssk.g; // error + +let i: I = { p: 12, m() { }, get g() { return 0; } }; let si = { ...i }; let ssi = { ...i, ...i }; si.p; si.m(); // ok +si.g; // ok ssi.p; ssi.m(); // ok -let o = { p: 12, m() { } }; +ssi.g; // ok + +let o = { p: 12, m() { }, get g() { return 0; } }; let so = { ...o }; let sso = { ...o, ...o }; so.p; so.m(); // ok +so.g; // ok sso.p; sso.m(); // ok +sso.g; // ok