Skip to content

Commit 718e66b

Browse files
author
Andy Hanson
committed
Don't include class getter in spread type
1 parent 1a05f13 commit 718e66b

File tree

6 files changed

+281
-139
lines changed

6 files changed

+281
-139
lines changed

src/compiler/checker.ts

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4461,10 +4461,7 @@ namespace ts {
44614461
names.set(getTextOfPropertyName(name), true);
44624462
}
44634463
for (const prop of getPropertiesOfType(source)) {
4464-
const inNamesToRemove = names.has(prop.escapedName);
4465-
const isPrivate = getDeclarationModifierFlagsFromSymbol(prop) & (ModifierFlags.Private | ModifierFlags.Protected);
4466-
const isSetOnlyAccessor = prop.flags & SymbolFlags.SetAccessor && !(prop.flags & SymbolFlags.GetAccessor);
4467-
if (!inNamesToRemove && !isPrivate && !isClassMethod(prop) && !isSetOnlyAccessor) {
4464+
if (!names.has(prop.escapedName) && !(getDeclarationModifierFlagsFromSymbol(prop) & (ModifierFlags.Private | ModifierFlags.Protected)) && isSpreadableProperty(prop)) {
44684465
members.set(prop.escapedName, getNonReadonlySymbol(prop));
44694466
}
44704467
}
@@ -9646,20 +9643,16 @@ namespace ts {
96469643
}
96479644

96489645
for (const rightProp of getPropertiesOfType(right)) {
9649-
// we approximate own properties as non-methods plus methods that are inside the object literal
9650-
const isSetterWithoutGetter = rightProp.flags & SymbolFlags.SetAccessor && !(rightProp.flags & SymbolFlags.GetAccessor);
96519646
if (getDeclarationModifierFlagsFromSymbol(rightProp) & (ModifierFlags.Private | ModifierFlags.Protected)) {
96529647
skippedPrivateMembers.set(rightProp.escapedName, true);
96539648
}
9654-
else if (!isClassMethod(rightProp) && !isSetterWithoutGetter) {
9649+
else if (isSpreadableProperty(rightProp)) {
96559650
members.set(rightProp.escapedName, getNonReadonlySymbol(rightProp));
96569651
}
96579652
}
96589653

96599654
for (const leftProp of getPropertiesOfType(left)) {
9660-
if (leftProp.flags & SymbolFlags.SetAccessor && !(leftProp.flags & SymbolFlags.GetAccessor)
9661-
|| skippedPrivateMembers.has(leftProp.escapedName)
9662-
|| isClassMethod(leftProp)) {
9655+
if (skippedPrivateMembers.has(leftProp.escapedName) || !isSpreadableProperty(leftProp)) {
96639656
continue;
96649657
}
96659658
if (members.has(leftProp.escapedName)) {
@@ -9694,6 +9687,13 @@ namespace ts {
96949687
return spread;
96959688
}
96969689

9690+
function isSpreadableProperty(prop: Symbol): boolean {
9691+
// We approximate own properties as non-methods plus methods that are inside the object literal
9692+
return prop.flags & (SymbolFlags.Method | SymbolFlags.GetAccessor)
9693+
? !prop.declarations.some(decl => isClassLike(decl.parent))
9694+
: !(prop.flags & SymbolFlags.SetAccessor); // Setter without getter is not spreadable
9695+
}
9696+
96979697
function getNonReadonlySymbol(prop: Symbol) {
96989698
if (!isReadonlySymbol(prop)) {
96999699
return prop;
@@ -9714,10 +9714,6 @@ namespace ts {
97149714
return index;
97159715
}
97169716

9717-
function isClassMethod(prop: Symbol) {
9718-
return prop.flags & SymbolFlags.Method && find(prop.declarations, decl => isClassLike(decl.parent));
9719-
}
9720-
97219717
function createLiteralType(flags: TypeFlags, value: string | number, symbol: Symbol | undefined) {
97229718
const type = <LiteralType>createType(flags);
97239719
type.symbol = symbol!;
Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,56 @@
1-
tests/cases/conformance/types/spread/spreadMethods.ts(7,4): error TS2339: Property 'm' does not exist on type '{ p: number; }'.
2-
tests/cases/conformance/types/spread/spreadMethods.ts(9,5): error TS2339: Property 'm' does not exist on type '{ p: number; }'.
1+
tests/cases/conformance/types/spread/spreadMethods.ts(16,4): error TS2339: Property 'm' does not exist on type '{ p: number; }'.
2+
tests/cases/conformance/types/spread/spreadMethods.ts(17,4): error TS2339: Property 'g' does not exist on type '{ p: number; }'.
3+
tests/cases/conformance/types/spread/spreadMethods.ts(19,5): error TS2339: Property 'm' does not exist on type '{ p: number; }'.
4+
tests/cases/conformance/types/spread/spreadMethods.ts(20,5): error TS2339: Property 'g' does not exist on type '{ p: number; }'.
35

46

5-
==== tests/cases/conformance/types/spread/spreadMethods.ts (2 errors) ====
6-
class K { p = 12; m() { } }
7-
interface I { p: number, m(): void }
7+
==== tests/cases/conformance/types/spread/spreadMethods.ts (4 errors) ====
8+
class K {
9+
p = 12;
10+
m() { }
11+
get g() { return 0; }
12+
}
13+
interface I {
14+
p: number;
15+
m(): void;
16+
readonly g: number;
17+
}
18+
819
let k = new K()
920
let sk = { ...k };
1021
let ssk = { ...k, ...k };
1122
sk.p;
1223
sk.m(); // error
1324
~
1425
!!! error TS2339: Property 'm' does not exist on type '{ p: number; }'.
26+
sk.g; // error
27+
~
28+
!!! error TS2339: Property 'g' does not exist on type '{ p: number; }'.
1529
ssk.p;
1630
ssk.m(); // error
1731
~
1832
!!! error TS2339: Property 'm' does not exist on type '{ p: number; }'.
19-
let i: I = { p: 12, m() { } };
33+
ssk.g; // error
34+
~
35+
!!! error TS2339: Property 'g' does not exist on type '{ p: number; }'.
36+
37+
let i: I = { p: 12, m() { }, get g() { return 0; } };
2038
let si = { ...i };
2139
let ssi = { ...i, ...i };
2240
si.p;
2341
si.m(); // ok
42+
si.g; // ok
2443
ssi.p;
2544
ssi.m(); // ok
26-
let o = { p: 12, m() { } };
45+
ssi.g; // ok
46+
47+
let o = { p: 12, m() { }, get g() { return 0; } };
2748
let so = { ...o };
2849
let sso = { ...o, ...o };
2950
so.p;
3051
so.m(); // ok
52+
so.g; // ok
3153
sso.p;
3254
sso.m(); // ok
55+
sso.g; // ok
3356

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,78 @@
11
//// [spreadMethods.ts]
2-
class K { p = 12; m() { } }
3-
interface I { p: number, m(): void }
2+
class K {
3+
p = 12;
4+
m() { }
5+
get g() { return 0; }
6+
}
7+
interface I {
8+
p: number;
9+
m(): void;
10+
readonly g: number;
11+
}
12+
413
let k = new K()
514
let sk = { ...k };
615
let ssk = { ...k, ...k };
716
sk.p;
817
sk.m(); // error
18+
sk.g; // error
919
ssk.p;
1020
ssk.m(); // error
11-
let i: I = { p: 12, m() { } };
21+
ssk.g; // error
22+
23+
let i: I = { p: 12, m() { }, get g() { return 0; } };
1224
let si = { ...i };
1325
let ssi = { ...i, ...i };
1426
si.p;
1527
si.m(); // ok
28+
si.g; // ok
1629
ssi.p;
1730
ssi.m(); // ok
18-
let o = { p: 12, m() { } };
31+
ssi.g; // ok
32+
33+
let o = { p: 12, m() { }, get g() { return 0; } };
1934
let so = { ...o };
2035
let sso = { ...o, ...o };
2136
so.p;
2237
so.m(); // ok
38+
so.g; // ok
2339
sso.p;
2440
sso.m(); // ok
41+
sso.g; // ok
2542

2643

2744
//// [spreadMethods.js]
28-
var __assign = (this && this.__assign) || function () {
29-
__assign = Object.assign || function(t) {
30-
for (var s, i = 1, n = arguments.length; i < n; i++) {
31-
s = arguments[i];
32-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
33-
t[p] = s[p];
34-
}
35-
return t;
36-
};
37-
return __assign.apply(this, arguments);
38-
};
39-
var K = /** @class */ (function () {
40-
function K() {
45+
class K {
46+
constructor() {
4147
this.p = 12;
4248
}
43-
K.prototype.m = function () { };
44-
return K;
45-
}());
46-
var k = new K();
47-
var sk = __assign({}, k);
48-
var ssk = __assign({}, k, k);
49+
m() { }
50+
get g() { return 0; }
51+
}
52+
let k = new K();
53+
let sk = { ...k };
54+
let ssk = { ...k, ...k };
4955
sk.p;
5056
sk.m(); // error
57+
sk.g; // error
5158
ssk.p;
5259
ssk.m(); // error
53-
var i = { p: 12, m: function () { } };
54-
var si = __assign({}, i);
55-
var ssi = __assign({}, i, i);
60+
ssk.g; // error
61+
let i = { p: 12, m() { }, get g() { return 0; } };
62+
let si = { ...i };
63+
let ssi = { ...i, ...i };
5664
si.p;
5765
si.m(); // ok
66+
si.g; // ok
5867
ssi.p;
5968
ssi.m(); // ok
60-
var o = { p: 12, m: function () { } };
61-
var so = __assign({}, o);
62-
var sso = __assign({}, o, o);
69+
ssi.g; // ok
70+
let o = { p: 12, m() { }, get g() { return 0; } };
71+
let so = { ...o };
72+
let sso = { ...o, ...o };
6373
so.p;
6474
so.m(); // ok
75+
so.g; // ok
6576
sso.p;
6677
sso.m(); // ok
78+
sso.g; // ok

0 commit comments

Comments
 (0)