Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13085,12 +13085,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
let lateSymbol = lateSymbols.get(memberName);
if (!lateSymbol) lateSymbols.set(memberName, lateSymbol = createSymbol(SymbolFlags.None, memberName, CheckFlags.Late));

// Report an error if a late-bound member has the same name as an early-bound member,
// or if we have another early-bound symbol declaration with the same name and
// conflicting flags.
// Report an error if there's a symbol declaration with the same name and conflicting flags.
const earlySymbol = earlySymbols && earlySymbols.get(memberName);
// Duplicate property declarations of classes are checked in checkClassForDuplicateDeclarations.
if (!(parent.flags & SymbolFlags.Class) && (lateSymbol.flags & getExcludedSymbolFlags(symbolFlags) || earlySymbol)) {
if (!(parent.flags & SymbolFlags.Class) && lateSymbol.flags & getExcludedSymbolFlags(symbolFlags)) {
// If we have an existing early-bound member, combine its declarations so that we can
// report an error at each declaration.
const declarations = earlySymbol ? concatenate(earlySymbol.declarations, lateSymbol.declarations) : lateSymbol.declarations;
Expand Down
8 changes: 1 addition & 7 deletions tests/baselines/reference/dynamicNamesErrors.errors.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
dynamicNamesErrors.ts(5,5): error TS2718: Duplicate property '1'.
dynamicNamesErrors.ts(6,5): error TS2733: Property '1' was also declared here.
dynamicNamesErrors.ts(19,5): error TS2717: Subsequent property declarations must have the same type. Property '[c1]' must be of type 'number', but here has type 'string'.
dynamicNamesErrors.ts(24,1): error TS2322: Type 'T2' is not assignable to type 'T1'.
Types of property '[c0]' are incompatible.
Expand All @@ -9,17 +7,13 @@ dynamicNamesErrors.ts(25,1): error TS2322: Type 'T1' is not assignable to type '
Type 'number' is not assignable to type 'string'.


==== dynamicNamesErrors.ts (5 errors) ====
==== dynamicNamesErrors.ts (3 errors) ====
const c0 = "1";
const c1 = 1;

interface T0 {
[c0]: number;
~~~~
!!! error TS2718: Duplicate property '1'.
1: number;
~
!!! error TS2733: Property '1' was also declared here.
Comment on lines 15 to -22
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was going to say that this sure felt wrong, but your playground link does show that doing effectively this in other forms does not error. (Makes me wonder if we're missing errors; but that's more of a design question I don't have context for.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should allow it, but it's definitely a separate question -- and disallowing it will probably break some amount of code.

}

interface T1 {
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/dynamicNamesErrors.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ interface T0 {
>T0 : Symbol(T0, Decl(dynamicNamesErrors.ts, 1, 13))

[c0]: number;
>[c0] : Symbol(T0[c0], Decl(dynamicNamesErrors.ts, 3, 14))
>[c0] : Symbol(T0[1], Decl(dynamicNamesErrors.ts, 4, 17), Decl(dynamicNamesErrors.ts, 3, 14))
>c0 : Symbol(c0, Decl(dynamicNamesErrors.ts, 0, 5))

1: number;
>1 : Symbol(T0[1], Decl(dynamicNamesErrors.ts, 4, 17))
>1 : Symbol(T0[1], Decl(dynamicNamesErrors.ts, 4, 17), Decl(dynamicNamesErrors.ts, 3, 14))
}

interface T1 {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/// <reference path="fourslash.ts"/>

//// export {};

//// const prop = "abc";

//// function foo(): void {};
//// foo.abc = 10;
//// foo[prop] = 10;

//// interface T0 {
//// [prop]: number;
//// abc: number;
//// }

verify.noErrors();