question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Computed properties no throws if there is a duplicate

See original GitHub issue

TypeScript Version: 3.0.0-dev.20180712

Search Terms:

Code

const A = 'a';
const x = {[A]: 1, [A]: 'b'} // x is {[A]: string}

Expected behavior: Duplicate declaration error

Actual behavior: No error

Playground Link: https://www.typescriptlang.org/play/#src=const A %3D ‘a’%3B const x %3D {[A]%3A 1%2C [A]%3A 1}

Related Issues:

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:17
  • Comments:7 (1 by maintainers)

github_iconTop GitHub Comments

4reactions
MickeyPhoenixcommented, Sep 29, 2021

I explored the various cases where this occurs. I’ve recorded the actual errors received in each case. This was in VSCode, with TypeScript 4.4.2.

// Object literals are forbidden to define multiple properties with the same name in strict mode.
//
// In an object literal, property names can be defined in at least five different ways:
//    * as an identifier,
//    * as a quoted string in square brackets,
//    * as an enum value in square brackets,
//    * as a const variable in square brackets, and
//    * as an expression involving only constants in square brackets.
//
// Depending on the combination and order in which these representations occur,
// the TypeScript type checker may report some of the following errors, on one or both of the
// duplicate property definitions:
//    * An object literal cannot have multiple properties with the same name in strict mode.ts(1117)
//    * Duplicate identifier '<identifier>'.ts(2300)
//    * Property '<propertyName>' was also declared here.ts(2733)
//    * Duplicate property '<propertyName>'.ts(2718)
//
// In at least two of these cases, TypeScript returns no errors, even though the property name has
// already been determined by TypeScript (as can be demonstrated via other cases, in which an appropriate
// error is given).
// This gives the expected ts(1117) error, on the second occurrence of the property name.
// It also gives a ts(2300) error, on the second occurrence of the property name.
export const case1: object = {
  fred: 'value1',
  // error "An object literal cannot have multiple properties with the same name in strict mode.ts(1117)"
  // error "Duplicate identifier ''fred''.ts(2300)"
  fred: 'value2'
};
// This does not give the expected ts(1117) error.
// It does give a ts(2300) error, on the second occurrence of the property name.
export const case2: object = {
  ['fred']: 'value1',
  // error "Duplicate identifier '['fred']'.ts(2300)"
  fred: 'value2'
};
// This does not give the expected ts(1117) error.
// It does give a ts(2300) error, on the second occurrence of the property name.
export const case3: object = {
  fred: 'value1',
  // error "Duplicate identifier '['fred']'.ts(2300)"
  ['fred']: 'value2'
};
enum FredEnum {
  FRED = 'fred'
}
// This does not give the expected ts(1117) error.
// It also does not give the ts(2300) error.
// It gives a ts(2733) error on the first occurrence, correctly back-referencing the first occurrence
//    of the duplicate property name.
// It gives a ts(2718) error on the second occurrence, correctly identifying a duplicate property
//    (although not identifying that it is a duplicate property name *in an object literal*).
export const case4: object = {
  // error "Property 'fred' was also declared here.ts(2733)"
  fred: 'value1',
  // error "Duplicate property 'fred'.ts(2718)"
  [FredEnum.FRED]: 'value2'
};
// This does not give the expected ts(1117) error.
// It also does not give the ts(2300) error.
// It gives a ts(2718) error on the first occurrence, incorrectly identifying the first occurrence
//    of the duplicate property name as a duplicate (although not identifying that it is a duplicate
//    property name *in an object literal*).
// It gives a ts(2733) error on the second occurrence, confusingly describing the duplicate as though
//    it were the original occurrence of the duplicate property name.
export const case5: object = {
  // error "Duplicate property 'fred'.ts(2718)"
  [FredEnum.FRED]: 'value2',
  // error "Property 'fred' was also declared here.ts(2733)"
  fred: 'value1'
};
// Same behavior as case4 (the bare property name x enum value case).
export const case6: object = {
  // error "Property 'fred' was also declared here.ts(2733)"
  ['fred']: 'value1',
  // error "Duplicate property 'fred'.ts(2718)"
  [FredEnum.FRED]: 'value2'
};
// Same behavior as case5 (the enum value x bare property name case).
export const case7: object = {
  // error "Duplicate property 'fred'.ts(2718)"
  [FredEnum.FRED]: 'value2',
  // error "Property 'fred' was also declared here.ts(2733)"
  ['fred']: 'value1'
};
// No error given, even though the two property declarations have the same value -- and even though,
// as shown in cases 4-7, TypeScript *does* know, via static analysis, that the enum values have that
// value.
export const case8: object = {
  [FredEnum.FRED]: 'value1',
  [FredEnum.FRED]: 'value2'
};
const fredKey: 'fred' = 'fred';
// Same as case4
export const case9: object = {
  // error "Property 'fred' was also declared here.ts(2733)"
  fred: 'value1',
  // error "Duplicate property 'fred'.ts(2718)"
  [fredKey]: 'value2'
};
// Same as case5
export const case10: object = {
  // error "Duplicate property 'fred'.ts(2718)"
  [fredKey]: 'value1',
  // error "Property 'fred' was also declared here.ts(2733)"
  fred: 'value2'
};
// Same as case6
export const case11: object = {
  // error "Property 'fred' was also declared here.ts(2733)"
  fred: 'value1',
  // error "Duplicate property 'fred'.ts(2718)"
  [fredKey]: 'value2'
};
// Same as case7
export const case12: object = {
  // error "Duplicate property 'fred'.ts(2718)"
  [fredKey]: 'value1',
  // error "Property 'fred' was also declared here.ts(2733)"
  fred: 'value2'
};
// Same as case8
export const case13: object = {
  [fredKey]: 'value1',
  [fredKey]: 'value2'
};
// No error given, even though the two property declarations have the same value -- and even though,
// as shown in cases 4-7 and 9-13, TypeScript *does* know, via static analysis, that the enum values
// have that value.
export const case14: object = {
  [FredEnum.FRED]: 'value1',
  [fredKey]: 'value2'
};
3reactions
MickeyPhoenixcommented, Sep 29, 2021

It would be ideal if all of the above cases gave the same errors, rather than mixing and matching the four different errors across the different cases.

My personal preference would be for three errors in every case:

  • On the second occurrence (and any further occurrences): – “An object literal cannot have multiple properties with the same name in strict mode.ts(1117)” – “Duplicate property ‘fred’.ts(2718)”
  • On the first occurrence of a given property name: – “Property ‘fred’ was also declared here.ts(2733)”

In addition to the bug where some duplicated property names show no error at all, I believe that the following cases are also bugs:

  • The error “Duplicate identifier ‘<identifier>’.ts(2300)” does not accurately describe what’s going on in any of the above cases, and is potentially very misleading.
  • It is incorrect to show the error “Duplicate property ‘fred’.ts(2718)” on the first occurrence of the property name, and “Property ‘fred’ was also declared here.ts(2733)” on the second occurrence of the property name.
Read more comments on GitHub >

github_iconTop Results From Across the Web

What's the purpose of allowing duplicate property names?
In ECMAScript 5 strict mode code, duplicate property names were considered a SyntaxError. With the introduction of computed property names ...
Read more >
Object initializer - JavaScript - MDN Web Docs - Mozilla
In ECMAScript 5 strict mode code, duplicate property names were considered a SyntaxError . With the introduction of computed property names ...
Read more >
Computed properties in Swift: A basic feature for safer and ...
In a real app, it's unlikely that that will happen in a single place. That duplicates code, which makes it likelier to make...
Read more >
Computed Properties and Entity Framework - Dave Glick
The AccountValue property in the first example above will throw a null reference until Holdings has been initialized. If you are only using ......
Read more >
Duplicate property names (was Re: @@new) - ES Discuss
... the constraint that duplicate dynamic object properties throw (in strict mode) ... both computed and static properties no longer have any duplicate...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found