diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 843267708dc..4ce6e195707 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -38763,8 +38763,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // both are private identifiers isPrivateIdentifier(node.name) && isPrivateIdentifier(subsequentName) && node.name.escapedText === subsequentName.escapedText || // Both are computed property names - // TODO: GH#17345: These are methods, so handle computed name case. (`Always allowing computed property names is *not* the correct behavior!) - isComputedPropertyName(node.name) && isComputedPropertyName(subsequentName) || + isComputedPropertyName(node.name) && isComputedPropertyName(subsequentName) && isTypeIdenticalTo(checkComputedPropertyName(node.name), checkComputedPropertyName(subsequentName)) || // Both are literal property names that are the same. isPropertyNameLiteral(node.name) && isPropertyNameLiteral(subsequentName) && getEscapedTextOfIdentifierOrLiteral(node.name) === getEscapedTextOfIdentifierOrLiteral(subsequentName) diff --git a/tests/baselines/reference/overloadsWithComputedNames.errors.txt b/tests/baselines/reference/overloadsWithComputedNames.errors.txt new file mode 100644 index 00000000000..a4d86db3d2c --- /dev/null +++ b/tests/baselines/reference/overloadsWithComputedNames.errors.txt @@ -0,0 +1,91 @@ +tests/cases/compiler/overloadsWithComputedNames.ts(4,5): error TS2389: Function implementation name must be '["B"]'. +tests/cases/compiler/overloadsWithComputedNames.ts(14,5): error TS2391: Function implementation is missing or not immediately following the declaration. +tests/cases/compiler/overloadsWithComputedNames.ts(16,5): error TS2389: Function implementation name must be '["bar"]'. +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. +tests/cases/compiler/overloadsWithComputedNames.ts(29,5): error TS2391: Function implementation is missing or not immediately following the declaration. +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. +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. +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. +tests/cases/compiler/overloadsWithComputedNames.ts(52,5): error TS2391: Function implementation is missing or not immediately following the declaration. + + +==== tests/cases/compiler/overloadsWithComputedNames.ts (9 errors) ==== + // https://github.com/microsoft/TypeScript/issues/52329 + class Person { + ["B"](a: number): string; + ["A"](a: string|number): number | string { + ~~~~~ +!!! error TS2389: Function implementation name must be '["B"]'. + return 0; + } + } + let p = new Person(); + p.A(0) + p.B(0) + + // https://github.com/microsoft/TypeScript/issues/17345 + class C { + ["foo"](): void + ~~~~~~~ +!!! error TS2391: Function implementation is missing or not immediately following the declaration. + ["bar"](): void; + ["foo"]() { + ~~~~~~~ +!!! error TS2389: Function implementation name must be '["bar"]'. + return 0; + } + } + + declare const uniqueSym: unique symbol; + declare const uniqueSym2: unique symbol; + declare const sym: symbol; + + declare const strUnion: 'foo' | 'bar'; + + class C1 { + [sym](): void; // should error + ~~~~~ +!!! 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. + [uniqueSym2](): void; // should error + ~~~~~~~~~~~~ +!!! error TS2391: Function implementation is missing or not immediately following the declaration. + [uniqueSym](): void; + [uniqueSym]() { } + } + + interface I1 { + [sym](): void; // should error + ~~~~~ +!!! 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. + [uniqueSym2](): void; + [uniqueSym](): void; + [uniqueSym](): void; + } + + class C2 { + [strUnion](): void; // should error + ~~~~~~~~~~ +!!! 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. + [strUnion]() { } + } + + class I2 { + [strUnion](): void; // should error + ~~~~~~~~~~ +!!! 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. + [strUnion]() { } + } + + class C3 { + [1](): void; // should error + ~~~ +!!! error TS2391: Function implementation is missing or not immediately following the declaration. + [2](): void; + [2]() { } + } + + interface I3 { + [1](): void; + [2](): void; + [2](): void; + } \ No newline at end of file diff --git a/tests/baselines/reference/overloadsWithComputedNames.js b/tests/baselines/reference/overloadsWithComputedNames.js new file mode 100644 index 00000000000..a29ec192246 --- /dev/null +++ b/tests/baselines/reference/overloadsWithComputedNames.js @@ -0,0 +1,109 @@ +//// [overloadsWithComputedNames.ts] +// https://github.com/microsoft/TypeScript/issues/52329 +class Person { + ["B"](a: number): string; + ["A"](a: string|number): number | string { + return 0; + } +} +let p = new Person(); +p.A(0) +p.B(0) + +// https://github.com/microsoft/TypeScript/issues/17345 +class C { + ["foo"](): void + ["bar"](): void; + ["foo"]() { + return 0; + } +} + +declare const uniqueSym: unique symbol; +declare const uniqueSym2: unique symbol; +declare const sym: symbol; + +declare const strUnion: 'foo' | 'bar'; + +class C1 { + [sym](): void; // should error + [uniqueSym2](): void; // should error + [uniqueSym](): void; + [uniqueSym]() { } +} + +interface I1 { + [sym](): void; // should error + [uniqueSym2](): void; + [uniqueSym](): void; + [uniqueSym](): void; +} + +class C2 { + [strUnion](): void; // should error + [strUnion]() { } +} + +class I2 { + [strUnion](): void; // should error + [strUnion]() { } +} + +class C3 { + [1](): void; // should error + [2](): void; + [2]() { } +} + +interface I3 { + [1](): void; + [2](): void; + [2](): void; +} + +//// [overloadsWithComputedNames.js] +// https://github.com/microsoft/TypeScript/issues/52329 +var Person = /** @class */ (function () { + function Person() { + } + Person.prototype["A"] = function (a) { + return 0; + }; + return Person; +}()); +var p = new Person(); +p.A(0); +p.B(0); +// https://github.com/microsoft/TypeScript/issues/17345 +var C = /** @class */ (function () { + function C() { + } + C.prototype["foo"] = function () { + return 0; + }; + return C; +}()); +var C1 = /** @class */ (function () { + function C1() { + } + C1.prototype[uniqueSym] = function () { }; + return C1; +}()); +var C2 = /** @class */ (function () { + function C2() { + } + C2.prototype[strUnion] = function () { }; + return C2; +}()); +var I2 = /** @class */ (function () { + function I2() { + } + I2.prototype[strUnion] = function () { }; + return I2; +}()); +var C3 = /** @class */ (function () { + function C3() { + } + C3.prototype[2] = function () { }; + return C3; +}()); diff --git a/tests/baselines/reference/overloadsWithComputedNames.symbols b/tests/baselines/reference/overloadsWithComputedNames.symbols new file mode 100644 index 00000000000..4b4e7c35008 --- /dev/null +++ b/tests/baselines/reference/overloadsWithComputedNames.symbols @@ -0,0 +1,159 @@ +=== tests/cases/compiler/overloadsWithComputedNames.ts === +// https://github.com/microsoft/TypeScript/issues/52329 +class Person { +>Person : Symbol(Person, Decl(overloadsWithComputedNames.ts, 0, 0)) + + ["B"](a: number): string; +>["B"] : Symbol(Person["B"], Decl(overloadsWithComputedNames.ts, 1, 14)) +>"B" : Symbol(Person["B"], Decl(overloadsWithComputedNames.ts, 1, 14)) +>a : Symbol(a, Decl(overloadsWithComputedNames.ts, 2, 10)) + + ["A"](a: string|number): number | string { +>["A"] : Symbol(Person["A"], Decl(overloadsWithComputedNames.ts, 2, 29)) +>"A" : Symbol(Person["A"], Decl(overloadsWithComputedNames.ts, 2, 29)) +>a : Symbol(a, Decl(overloadsWithComputedNames.ts, 3, 10)) + + return 0; + } +} +let p = new Person(); +>p : Symbol(p, Decl(overloadsWithComputedNames.ts, 7, 3)) +>Person : Symbol(Person, Decl(overloadsWithComputedNames.ts, 0, 0)) + +p.A(0) +>p.A : Symbol(Person["A"], Decl(overloadsWithComputedNames.ts, 2, 29)) +>p : Symbol(p, Decl(overloadsWithComputedNames.ts, 7, 3)) +>A : Symbol(Person["A"], Decl(overloadsWithComputedNames.ts, 2, 29)) + +p.B(0) +>p.B : Symbol(Person["B"], Decl(overloadsWithComputedNames.ts, 1, 14)) +>p : Symbol(p, Decl(overloadsWithComputedNames.ts, 7, 3)) +>B : Symbol(Person["B"], Decl(overloadsWithComputedNames.ts, 1, 14)) + +// https://github.com/microsoft/TypeScript/issues/17345 +class C { +>C : Symbol(C, Decl(overloadsWithComputedNames.ts, 9, 6)) + + ["foo"](): void +>["foo"] : Symbol(C["foo"], Decl(overloadsWithComputedNames.ts, 12, 9), Decl(overloadsWithComputedNames.ts, 14, 20)) +>"foo" : Symbol(C["foo"], Decl(overloadsWithComputedNames.ts, 12, 9), Decl(overloadsWithComputedNames.ts, 14, 20)) + + ["bar"](): void; +>["bar"] : Symbol(C["bar"], Decl(overloadsWithComputedNames.ts, 13, 19)) +>"bar" : Symbol(C["bar"], Decl(overloadsWithComputedNames.ts, 13, 19)) + + ["foo"]() { +>["foo"] : Symbol(C["foo"], Decl(overloadsWithComputedNames.ts, 12, 9), Decl(overloadsWithComputedNames.ts, 14, 20)) +>"foo" : Symbol(C["foo"], Decl(overloadsWithComputedNames.ts, 12, 9), Decl(overloadsWithComputedNames.ts, 14, 20)) + + return 0; + } +} + +declare const uniqueSym: unique symbol; +>uniqueSym : Symbol(uniqueSym, Decl(overloadsWithComputedNames.ts, 20, 13)) + +declare const uniqueSym2: unique symbol; +>uniqueSym2 : Symbol(uniqueSym2, Decl(overloadsWithComputedNames.ts, 21, 13)) + +declare const sym: symbol; +>sym : Symbol(sym, Decl(overloadsWithComputedNames.ts, 22, 13)) + +declare const strUnion: 'foo' | 'bar'; +>strUnion : Symbol(strUnion, Decl(overloadsWithComputedNames.ts, 24, 13)) + +class C1 { +>C1 : Symbol(C1, Decl(overloadsWithComputedNames.ts, 24, 38)) + + [sym](): void; // should error +>[sym] : Symbol(C1[sym], Decl(overloadsWithComputedNames.ts, 26, 10)) +>sym : Symbol(sym, Decl(overloadsWithComputedNames.ts, 22, 13)) + + [uniqueSym2](): void; // should error +>[uniqueSym2] : Symbol(C1[uniqueSym2], Decl(overloadsWithComputedNames.ts, 27, 18)) +>uniqueSym2 : Symbol(uniqueSym2, Decl(overloadsWithComputedNames.ts, 21, 13)) + + [uniqueSym](): void; +>[uniqueSym] : Symbol(C1[uniqueSym], Decl(overloadsWithComputedNames.ts, 28, 25), Decl(overloadsWithComputedNames.ts, 29, 24)) +>uniqueSym : Symbol(uniqueSym, Decl(overloadsWithComputedNames.ts, 20, 13)) + + [uniqueSym]() { } +>[uniqueSym] : Symbol(C1[uniqueSym], Decl(overloadsWithComputedNames.ts, 28, 25), Decl(overloadsWithComputedNames.ts, 29, 24)) +>uniqueSym : Symbol(uniqueSym, Decl(overloadsWithComputedNames.ts, 20, 13)) +} + +interface I1 { +>I1 : Symbol(I1, Decl(overloadsWithComputedNames.ts, 31, 1)) + + [sym](): void; // should error +>[sym] : Symbol(I1[sym], Decl(overloadsWithComputedNames.ts, 33, 14)) +>sym : Symbol(sym, Decl(overloadsWithComputedNames.ts, 22, 13)) + + [uniqueSym2](): void; +>[uniqueSym2] : Symbol(I1[uniqueSym2], Decl(overloadsWithComputedNames.ts, 34, 18)) +>uniqueSym2 : Symbol(uniqueSym2, Decl(overloadsWithComputedNames.ts, 21, 13)) + + [uniqueSym](): void; +>[uniqueSym] : Symbol(I1[uniqueSym], Decl(overloadsWithComputedNames.ts, 35, 25), Decl(overloadsWithComputedNames.ts, 36, 24)) +>uniqueSym : Symbol(uniqueSym, Decl(overloadsWithComputedNames.ts, 20, 13)) + + [uniqueSym](): void; +>[uniqueSym] : Symbol(I1[uniqueSym], Decl(overloadsWithComputedNames.ts, 35, 25), Decl(overloadsWithComputedNames.ts, 36, 24)) +>uniqueSym : Symbol(uniqueSym, Decl(overloadsWithComputedNames.ts, 20, 13)) +} + +class C2 { +>C2 : Symbol(C2, Decl(overloadsWithComputedNames.ts, 38, 1)) + + [strUnion](): void; // should error +>[strUnion] : Symbol(C2[strUnion], Decl(overloadsWithComputedNames.ts, 40, 10)) +>strUnion : Symbol(strUnion, Decl(overloadsWithComputedNames.ts, 24, 13)) + + [strUnion]() { } +>[strUnion] : Symbol(C2[strUnion], Decl(overloadsWithComputedNames.ts, 41, 23)) +>strUnion : Symbol(strUnion, Decl(overloadsWithComputedNames.ts, 24, 13)) +} + +class I2 { +>I2 : Symbol(I2, Decl(overloadsWithComputedNames.ts, 43, 1)) + + [strUnion](): void; // should error +>[strUnion] : Symbol(I2[strUnion], Decl(overloadsWithComputedNames.ts, 45, 10)) +>strUnion : Symbol(strUnion, Decl(overloadsWithComputedNames.ts, 24, 13)) + + [strUnion]() { } +>[strUnion] : Symbol(I2[strUnion], Decl(overloadsWithComputedNames.ts, 46, 23)) +>strUnion : Symbol(strUnion, Decl(overloadsWithComputedNames.ts, 24, 13)) +} + +class C3 { +>C3 : Symbol(C3, Decl(overloadsWithComputedNames.ts, 48, 1)) + + [1](): void; // should error +>[1] : Symbol(C3[1], Decl(overloadsWithComputedNames.ts, 50, 10)) +>1 : Symbol(C3[1], Decl(overloadsWithComputedNames.ts, 50, 10)) + + [2](): void; +>[2] : Symbol(C3[2], Decl(overloadsWithComputedNames.ts, 51, 16), Decl(overloadsWithComputedNames.ts, 52, 16)) +>2 : Symbol(C3[2], Decl(overloadsWithComputedNames.ts, 51, 16), Decl(overloadsWithComputedNames.ts, 52, 16)) + + [2]() { } +>[2] : Symbol(C3[2], Decl(overloadsWithComputedNames.ts, 51, 16), Decl(overloadsWithComputedNames.ts, 52, 16)) +>2 : Symbol(C3[2], Decl(overloadsWithComputedNames.ts, 51, 16), Decl(overloadsWithComputedNames.ts, 52, 16)) +} + +interface I3 { +>I3 : Symbol(I3, Decl(overloadsWithComputedNames.ts, 54, 1)) + + [1](): void; +>[1] : Symbol(I3[1], Decl(overloadsWithComputedNames.ts, 56, 14)) +>1 : Symbol(I3[1], Decl(overloadsWithComputedNames.ts, 56, 14)) + + [2](): void; +>[2] : Symbol(I3[2], Decl(overloadsWithComputedNames.ts, 57, 16), Decl(overloadsWithComputedNames.ts, 58, 16)) +>2 : Symbol(I3[2], Decl(overloadsWithComputedNames.ts, 57, 16), Decl(overloadsWithComputedNames.ts, 58, 16)) + + [2](): void; +>[2] : Symbol(I3[2], Decl(overloadsWithComputedNames.ts, 57, 16), Decl(overloadsWithComputedNames.ts, 58, 16)) +>2 : Symbol(I3[2], Decl(overloadsWithComputedNames.ts, 57, 16), Decl(overloadsWithComputedNames.ts, 58, 16)) +} diff --git a/tests/baselines/reference/overloadsWithComputedNames.types b/tests/baselines/reference/overloadsWithComputedNames.types new file mode 100644 index 00000000000..e2dc84f55e3 --- /dev/null +++ b/tests/baselines/reference/overloadsWithComputedNames.types @@ -0,0 +1,162 @@ +=== tests/cases/compiler/overloadsWithComputedNames.ts === +// https://github.com/microsoft/TypeScript/issues/52329 +class Person { +>Person : Person + + ["B"](a: number): string; +>["B"] : (a: number) => string +>"B" : "B" +>a : number + + ["A"](a: string|number): number | string { +>["A"] : (a: string | number) => number | string +>"A" : "A" +>a : string | number + + return 0; +>0 : 0 + } +} +let p = new Person(); +>p : Person +>new Person() : Person +>Person : typeof Person + +p.A(0) +>p.A(0) : string | number +>p.A : (a: string | number) => string | number +>p : Person +>A : (a: string | number) => string | number +>0 : 0 + +p.B(0) +>p.B(0) : string +>p.B : (a: number) => string +>p : Person +>B : (a: number) => string +>0 : 0 + +// https://github.com/microsoft/TypeScript/issues/17345 +class C { +>C : C + + ["foo"](): void +>["foo"] : { (): void; (): number; } +>"foo" : "foo" + + ["bar"](): void; +>["bar"] : () => void +>"bar" : "bar" + + ["foo"]() { +>["foo"] : { (): void; (): number; } +>"foo" : "foo" + + return 0; +>0 : 0 + } +} + +declare const uniqueSym: unique symbol; +>uniqueSym : unique symbol + +declare const uniqueSym2: unique symbol; +>uniqueSym2 : unique symbol + +declare const sym: symbol; +>sym : symbol + +declare const strUnion: 'foo' | 'bar'; +>strUnion : "foo" | "bar" + +class C1 { +>C1 : C1 + + [sym](): void; // should error +>[sym] : () => void +>sym : symbol + + [uniqueSym2](): void; // should error +>[uniqueSym2] : () => void +>uniqueSym2 : unique symbol + + [uniqueSym](): void; +>[uniqueSym] : () => void +>uniqueSym : unique symbol + + [uniqueSym]() { } +>[uniqueSym] : () => void +>uniqueSym : unique symbol +} + +interface I1 { + [sym](): void; // should error +>[sym] : () => void +>sym : symbol + + [uniqueSym2](): void; +>[uniqueSym2] : () => void +>uniqueSym2 : unique symbol + + [uniqueSym](): void; +>[uniqueSym] : { (): void; (): void; } +>uniqueSym : unique symbol + + [uniqueSym](): void; +>[uniqueSym] : { (): void; (): void; } +>uniqueSym : unique symbol +} + +class C2 { +>C2 : C2 + + [strUnion](): void; // should error +>[strUnion] : () => void +>strUnion : "foo" | "bar" + + [strUnion]() { } +>[strUnion] : () => void +>strUnion : "foo" | "bar" +} + +class I2 { +>I2 : I2 + + [strUnion](): void; // should error +>[strUnion] : () => void +>strUnion : "foo" | "bar" + + [strUnion]() { } +>[strUnion] : () => void +>strUnion : "foo" | "bar" +} + +class C3 { +>C3 : C3 + + [1](): void; // should error +>[1] : () => void +>1 : 1 + + [2](): void; +>[2] : () => void +>2 : 2 + + [2]() { } +>[2] : () => void +>2 : 2 +} + +interface I3 { + [1](): void; +>[1] : () => void +>1 : 1 + + [2](): void; +>[2] : { (): void; (): void; } +>2 : 2 + + [2](): void; +>[2] : { (): void; (): void; } +>2 : 2 +} diff --git a/tests/cases/compiler/overloadsWithComputedNames.ts b/tests/cases/compiler/overloadsWithComputedNames.ts new file mode 100644 index 00000000000..810beff8887 --- /dev/null +++ b/tests/cases/compiler/overloadsWithComputedNames.ts @@ -0,0 +1,61 @@ +// https://github.com/microsoft/TypeScript/issues/52329 +class Person { + ["B"](a: number): string; + ["A"](a: string|number): number | string { + return 0; + } +} +let p = new Person(); +p.A(0) +p.B(0) + +// https://github.com/microsoft/TypeScript/issues/17345 +class C { + ["foo"](): void + ["bar"](): void; + ["foo"]() { + return 0; + } +} + +declare const uniqueSym: unique symbol; +declare const uniqueSym2: unique symbol; +declare const sym: symbol; + +declare const strUnion: 'foo' | 'bar'; + +class C1 { + [sym](): void; // should error + [uniqueSym2](): void; // should error + [uniqueSym](): void; + [uniqueSym]() { } +} + +interface I1 { + [sym](): void; // should error + [uniqueSym2](): void; + [uniqueSym](): void; + [uniqueSym](): void; +} + +class C2 { + [strUnion](): void; // should error + [strUnion]() { } +} + +class I2 { + [strUnion](): void; // should error + [strUnion]() { } +} + +class C3 { + [1](): void; // should error + [2](): void; + [2]() { } +} + +interface I3 { + [1](): void; + [2](): void; + [2](): void; +} \ No newline at end of file