Skip to content

Commit 0ce5517

Browse files
authored
check computed property names in overloads (microsoft#52427)
1 parent 746a6fe commit 0ce5517

File tree

6 files changed

+583
-2
lines changed

6 files changed

+583
-2
lines changed

src/compiler/checker.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38763,8 +38763,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3876338763
// both are private identifiers
3876438764
isPrivateIdentifier(node.name) && isPrivateIdentifier(subsequentName) && node.name.escapedText === subsequentName.escapedText ||
3876538765
// Both are computed property names
38766-
// TODO: GH#17345: These are methods, so handle computed name case. (`Always allowing computed property names is *not* the correct behavior!)
38767-
isComputedPropertyName(node.name) && isComputedPropertyName(subsequentName) ||
38766+
isComputedPropertyName(node.name) && isComputedPropertyName(subsequentName) && isTypeIdenticalTo(checkComputedPropertyName(node.name), checkComputedPropertyName(subsequentName)) ||
3876838767
// Both are literal property names that are the same.
3876938768
isPropertyNameLiteral(node.name) && isPropertyNameLiteral(subsequentName) &&
3877038769
getEscapedTextOfIdentifierOrLiteral(node.name) === getEscapedTextOfIdentifierOrLiteral(subsequentName)
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
tests/cases/compiler/overloadsWithComputedNames.ts(4,5): error TS2389: Function implementation name must be '["B"]'.
2+
tests/cases/compiler/overloadsWithComputedNames.ts(14,5): error TS2391: Function implementation is missing or not immediately following the declaration.
3+
tests/cases/compiler/overloadsWithComputedNames.ts(16,5): error TS2389: Function implementation name must be '["bar"]'.
4+
tests/cases/compiler/overloadsWithComputedNames.ts(28,5): error TS1168: A computed property name in a method overload must refer to an expression whose type is a literal type or a 'unique symbol' type.
5+
tests/cases/compiler/overloadsWithComputedNames.ts(29,5): error TS2391: Function implementation is missing or not immediately following the declaration.
6+
tests/cases/compiler/overloadsWithComputedNames.ts(35,5): error TS1169: A computed property name in an interface must refer to an expression whose type is a literal type or a 'unique symbol' type.
7+
tests/cases/compiler/overloadsWithComputedNames.ts(42,5): error TS1168: A computed property name in a method overload must refer to an expression whose type is a literal type or a 'unique symbol' type.
8+
tests/cases/compiler/overloadsWithComputedNames.ts(47,5): error TS1168: A computed property name in a method overload must refer to an expression whose type is a literal type or a 'unique symbol' type.
9+
tests/cases/compiler/overloadsWithComputedNames.ts(52,5): error TS2391: Function implementation is missing or not immediately following the declaration.
10+
11+
12+
==== tests/cases/compiler/overloadsWithComputedNames.ts (9 errors) ====
13+
// https://github.com/microsoft/TypeScript/issues/52329
14+
class Person {
15+
["B"](a: number): string;
16+
["A"](a: string|number): number | string {
17+
~~~~~
18+
!!! error TS2389: Function implementation name must be '["B"]'.
19+
return 0;
20+
}
21+
}
22+
let p = new Person();
23+
p.A(0)
24+
p.B(0)
25+
26+
// https://github.com/microsoft/TypeScript/issues/17345
27+
class C {
28+
["foo"](): void
29+
~~~~~~~
30+
!!! error TS2391: Function implementation is missing or not immediately following the declaration.
31+
["bar"](): void;
32+
["foo"]() {
33+
~~~~~~~
34+
!!! error TS2389: Function implementation name must be '["bar"]'.
35+
return 0;
36+
}
37+
}
38+
39+
declare const uniqueSym: unique symbol;
40+
declare const uniqueSym2: unique symbol;
41+
declare const sym: symbol;
42+
43+
declare const strUnion: 'foo' | 'bar';
44+
45+
class C1 {
46+
[sym](): void; // should error
47+
~~~~~
48+
!!! error TS1168: A computed property name in a method overload must refer to an expression whose type is a literal type or a 'unique symbol' type.
49+
[uniqueSym2](): void; // should error
50+
~~~~~~~~~~~~
51+
!!! error TS2391: Function implementation is missing or not immediately following the declaration.
52+
[uniqueSym](): void;
53+
[uniqueSym]() { }
54+
}
55+
56+
interface I1 {
57+
[sym](): void; // should error
58+
~~~~~
59+
!!! error TS1169: A computed property name in an interface must refer to an expression whose type is a literal type or a 'unique symbol' type.
60+
[uniqueSym2](): void;
61+
[uniqueSym](): void;
62+
[uniqueSym](): void;
63+
}
64+
65+
class C2 {
66+
[strUnion](): void; // should error
67+
~~~~~~~~~~
68+
!!! error TS1168: A computed property name in a method overload must refer to an expression whose type is a literal type or a 'unique symbol' type.
69+
[strUnion]() { }
70+
}
71+
72+
class I2 {
73+
[strUnion](): void; // should error
74+
~~~~~~~~~~
75+
!!! error TS1168: A computed property name in a method overload must refer to an expression whose type is a literal type or a 'unique symbol' type.
76+
[strUnion]() { }
77+
}
78+
79+
class C3 {
80+
[1](): void; // should error
81+
~~~
82+
!!! error TS2391: Function implementation is missing or not immediately following the declaration.
83+
[2](): void;
84+
[2]() { }
85+
}
86+
87+
interface I3 {
88+
[1](): void;
89+
[2](): void;
90+
[2](): void;
91+
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
//// [overloadsWithComputedNames.ts]
2+
// https://github.com/microsoft/TypeScript/issues/52329
3+
class Person {
4+
["B"](a: number): string;
5+
["A"](a: string|number): number | string {
6+
return 0;
7+
}
8+
}
9+
let p = new Person();
10+
p.A(0)
11+
p.B(0)
12+
13+
// https://github.com/microsoft/TypeScript/issues/17345
14+
class C {
15+
["foo"](): void
16+
["bar"](): void;
17+
["foo"]() {
18+
return 0;
19+
}
20+
}
21+
22+
declare const uniqueSym: unique symbol;
23+
declare const uniqueSym2: unique symbol;
24+
declare const sym: symbol;
25+
26+
declare const strUnion: 'foo' | 'bar';
27+
28+
class C1 {
29+
[sym](): void; // should error
30+
[uniqueSym2](): void; // should error
31+
[uniqueSym](): void;
32+
[uniqueSym]() { }
33+
}
34+
35+
interface I1 {
36+
[sym](): void; // should error
37+
[uniqueSym2](): void;
38+
[uniqueSym](): void;
39+
[uniqueSym](): void;
40+
}
41+
42+
class C2 {
43+
[strUnion](): void; // should error
44+
[strUnion]() { }
45+
}
46+
47+
class I2 {
48+
[strUnion](): void; // should error
49+
[strUnion]() { }
50+
}
51+
52+
class C3 {
53+
[1](): void; // should error
54+
[2](): void;
55+
[2]() { }
56+
}
57+
58+
interface I3 {
59+
[1](): void;
60+
[2](): void;
61+
[2](): void;
62+
}
63+
64+
//// [overloadsWithComputedNames.js]
65+
// https://github.com/microsoft/TypeScript/issues/52329
66+
var Person = /** @class */ (function () {
67+
function Person() {
68+
}
69+
Person.prototype["A"] = function (a) {
70+
return 0;
71+
};
72+
return Person;
73+
}());
74+
var p = new Person();
75+
p.A(0);
76+
p.B(0);
77+
// https://github.com/microsoft/TypeScript/issues/17345
78+
var C = /** @class */ (function () {
79+
function C() {
80+
}
81+
C.prototype["foo"] = function () {
82+
return 0;
83+
};
84+
return C;
85+
}());
86+
var C1 = /** @class */ (function () {
87+
function C1() {
88+
}
89+
C1.prototype[uniqueSym] = function () { };
90+
return C1;
91+
}());
92+
var C2 = /** @class */ (function () {
93+
function C2() {
94+
}
95+
C2.prototype[strUnion] = function () { };
96+
return C2;
97+
}());
98+
var I2 = /** @class */ (function () {
99+
function I2() {
100+
}
101+
I2.prototype[strUnion] = function () { };
102+
return I2;
103+
}());
104+
var C3 = /** @class */ (function () {
105+
function C3() {
106+
}
107+
C3.prototype[2] = function () { };
108+
return C3;
109+
}());
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
=== tests/cases/compiler/overloadsWithComputedNames.ts ===
2+
// https://github.com/microsoft/TypeScript/issues/52329
3+
class Person {
4+
>Person : Symbol(Person, Decl(overloadsWithComputedNames.ts, 0, 0))
5+
6+
["B"](a: number): string;
7+
>["B"] : Symbol(Person["B"], Decl(overloadsWithComputedNames.ts, 1, 14))
8+
>"B" : Symbol(Person["B"], Decl(overloadsWithComputedNames.ts, 1, 14))
9+
>a : Symbol(a, Decl(overloadsWithComputedNames.ts, 2, 10))
10+
11+
["A"](a: string|number): number | string {
12+
>["A"] : Symbol(Person["A"], Decl(overloadsWithComputedNames.ts, 2, 29))
13+
>"A" : Symbol(Person["A"], Decl(overloadsWithComputedNames.ts, 2, 29))
14+
>a : Symbol(a, Decl(overloadsWithComputedNames.ts, 3, 10))
15+
16+
return 0;
17+
}
18+
}
19+
let p = new Person();
20+
>p : Symbol(p, Decl(overloadsWithComputedNames.ts, 7, 3))
21+
>Person : Symbol(Person, Decl(overloadsWithComputedNames.ts, 0, 0))
22+
23+
p.A(0)
24+
>p.A : Symbol(Person["A"], Decl(overloadsWithComputedNames.ts, 2, 29))
25+
>p : Symbol(p, Decl(overloadsWithComputedNames.ts, 7, 3))
26+
>A : Symbol(Person["A"], Decl(overloadsWithComputedNames.ts, 2, 29))
27+
28+
p.B(0)
29+
>p.B : Symbol(Person["B"], Decl(overloadsWithComputedNames.ts, 1, 14))
30+
>p : Symbol(p, Decl(overloadsWithComputedNames.ts, 7, 3))
31+
>B : Symbol(Person["B"], Decl(overloadsWithComputedNames.ts, 1, 14))
32+
33+
// https://github.com/microsoft/TypeScript/issues/17345
34+
class C {
35+
>C : Symbol(C, Decl(overloadsWithComputedNames.ts, 9, 6))
36+
37+
["foo"](): void
38+
>["foo"] : Symbol(C["foo"], Decl(overloadsWithComputedNames.ts, 12, 9), Decl(overloadsWithComputedNames.ts, 14, 20))
39+
>"foo" : Symbol(C["foo"], Decl(overloadsWithComputedNames.ts, 12, 9), Decl(overloadsWithComputedNames.ts, 14, 20))
40+
41+
["bar"](): void;
42+
>["bar"] : Symbol(C["bar"], Decl(overloadsWithComputedNames.ts, 13, 19))
43+
>"bar" : Symbol(C["bar"], Decl(overloadsWithComputedNames.ts, 13, 19))
44+
45+
["foo"]() {
46+
>["foo"] : Symbol(C["foo"], Decl(overloadsWithComputedNames.ts, 12, 9), Decl(overloadsWithComputedNames.ts, 14, 20))
47+
>"foo" : Symbol(C["foo"], Decl(overloadsWithComputedNames.ts, 12, 9), Decl(overloadsWithComputedNames.ts, 14, 20))
48+
49+
return 0;
50+
}
51+
}
52+
53+
declare const uniqueSym: unique symbol;
54+
>uniqueSym : Symbol(uniqueSym, Decl(overloadsWithComputedNames.ts, 20, 13))
55+
56+
declare const uniqueSym2: unique symbol;
57+
>uniqueSym2 : Symbol(uniqueSym2, Decl(overloadsWithComputedNames.ts, 21, 13))
58+
59+
declare const sym: symbol;
60+
>sym : Symbol(sym, Decl(overloadsWithComputedNames.ts, 22, 13))
61+
62+
declare const strUnion: 'foo' | 'bar';
63+
>strUnion : Symbol(strUnion, Decl(overloadsWithComputedNames.ts, 24, 13))
64+
65+
class C1 {
66+
>C1 : Symbol(C1, Decl(overloadsWithComputedNames.ts, 24, 38))
67+
68+
[sym](): void; // should error
69+
>[sym] : Symbol(C1[sym], Decl(overloadsWithComputedNames.ts, 26, 10))
70+
>sym : Symbol(sym, Decl(overloadsWithComputedNames.ts, 22, 13))
71+
72+
[uniqueSym2](): void; // should error
73+
>[uniqueSym2] : Symbol(C1[uniqueSym2], Decl(overloadsWithComputedNames.ts, 27, 18))
74+
>uniqueSym2 : Symbol(uniqueSym2, Decl(overloadsWithComputedNames.ts, 21, 13))
75+
76+
[uniqueSym](): void;
77+
>[uniqueSym] : Symbol(C1[uniqueSym], Decl(overloadsWithComputedNames.ts, 28, 25), Decl(overloadsWithComputedNames.ts, 29, 24))
78+
>uniqueSym : Symbol(uniqueSym, Decl(overloadsWithComputedNames.ts, 20, 13))
79+
80+
[uniqueSym]() { }
81+
>[uniqueSym] : Symbol(C1[uniqueSym], Decl(overloadsWithComputedNames.ts, 28, 25), Decl(overloadsWithComputedNames.ts, 29, 24))
82+
>uniqueSym : Symbol(uniqueSym, Decl(overloadsWithComputedNames.ts, 20, 13))
83+
}
84+
85+
interface I1 {
86+
>I1 : Symbol(I1, Decl(overloadsWithComputedNames.ts, 31, 1))
87+
88+
[sym](): void; // should error
89+
>[sym] : Symbol(I1[sym], Decl(overloadsWithComputedNames.ts, 33, 14))
90+
>sym : Symbol(sym, Decl(overloadsWithComputedNames.ts, 22, 13))
91+
92+
[uniqueSym2](): void;
93+
>[uniqueSym2] : Symbol(I1[uniqueSym2], Decl(overloadsWithComputedNames.ts, 34, 18))
94+
>uniqueSym2 : Symbol(uniqueSym2, Decl(overloadsWithComputedNames.ts, 21, 13))
95+
96+
[uniqueSym](): void;
97+
>[uniqueSym] : Symbol(I1[uniqueSym], Decl(overloadsWithComputedNames.ts, 35, 25), Decl(overloadsWithComputedNames.ts, 36, 24))
98+
>uniqueSym : Symbol(uniqueSym, Decl(overloadsWithComputedNames.ts, 20, 13))
99+
100+
[uniqueSym](): void;
101+
>[uniqueSym] : Symbol(I1[uniqueSym], Decl(overloadsWithComputedNames.ts, 35, 25), Decl(overloadsWithComputedNames.ts, 36, 24))
102+
>uniqueSym : Symbol(uniqueSym, Decl(overloadsWithComputedNames.ts, 20, 13))
103+
}
104+
105+
class C2 {
106+
>C2 : Symbol(C2, Decl(overloadsWithComputedNames.ts, 38, 1))
107+
108+
[strUnion](): void; // should error
109+
>[strUnion] : Symbol(C2[strUnion], Decl(overloadsWithComputedNames.ts, 40, 10))
110+
>strUnion : Symbol(strUnion, Decl(overloadsWithComputedNames.ts, 24, 13))
111+
112+
[strUnion]() { }
113+
>[strUnion] : Symbol(C2[strUnion], Decl(overloadsWithComputedNames.ts, 41, 23))
114+
>strUnion : Symbol(strUnion, Decl(overloadsWithComputedNames.ts, 24, 13))
115+
}
116+
117+
class I2 {
118+
>I2 : Symbol(I2, Decl(overloadsWithComputedNames.ts, 43, 1))
119+
120+
[strUnion](): void; // should error
121+
>[strUnion] : Symbol(I2[strUnion], Decl(overloadsWithComputedNames.ts, 45, 10))
122+
>strUnion : Symbol(strUnion, Decl(overloadsWithComputedNames.ts, 24, 13))
123+
124+
[strUnion]() { }
125+
>[strUnion] : Symbol(I2[strUnion], Decl(overloadsWithComputedNames.ts, 46, 23))
126+
>strUnion : Symbol(strUnion, Decl(overloadsWithComputedNames.ts, 24, 13))
127+
}
128+
129+
class C3 {
130+
>C3 : Symbol(C3, Decl(overloadsWithComputedNames.ts, 48, 1))
131+
132+
[1](): void; // should error
133+
>[1] : Symbol(C3[1], Decl(overloadsWithComputedNames.ts, 50, 10))
134+
>1 : Symbol(C3[1], Decl(overloadsWithComputedNames.ts, 50, 10))
135+
136+
[2](): void;
137+
>[2] : Symbol(C3[2], Decl(overloadsWithComputedNames.ts, 51, 16), Decl(overloadsWithComputedNames.ts, 52, 16))
138+
>2 : Symbol(C3[2], Decl(overloadsWithComputedNames.ts, 51, 16), Decl(overloadsWithComputedNames.ts, 52, 16))
139+
140+
[2]() { }
141+
>[2] : Symbol(C3[2], Decl(overloadsWithComputedNames.ts, 51, 16), Decl(overloadsWithComputedNames.ts, 52, 16))
142+
>2 : Symbol(C3[2], Decl(overloadsWithComputedNames.ts, 51, 16), Decl(overloadsWithComputedNames.ts, 52, 16))
143+
}
144+
145+
interface I3 {
146+
>I3 : Symbol(I3, Decl(overloadsWithComputedNames.ts, 54, 1))
147+
148+
[1](): void;
149+
>[1] : Symbol(I3[1], Decl(overloadsWithComputedNames.ts, 56, 14))
150+
>1 : Symbol(I3[1], Decl(overloadsWithComputedNames.ts, 56, 14))
151+
152+
[2](): void;
153+
>[2] : Symbol(I3[2], Decl(overloadsWithComputedNames.ts, 57, 16), Decl(overloadsWithComputedNames.ts, 58, 16))
154+
>2 : Symbol(I3[2], Decl(overloadsWithComputedNames.ts, 57, 16), Decl(overloadsWithComputedNames.ts, 58, 16))
155+
156+
[2](): void;
157+
>[2] : Symbol(I3[2], Decl(overloadsWithComputedNames.ts, 57, 16), Decl(overloadsWithComputedNames.ts, 58, 16))
158+
>2 : Symbol(I3[2], Decl(overloadsWithComputedNames.ts, 57, 16), Decl(overloadsWithComputedNames.ts, 58, 16))
159+
}

0 commit comments

Comments
 (0)