Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Computed properties no throws if there is a duplicate #25758

Closed
cevek opened this issue Jul 18, 2018 · 7 comments · Fixed by #49848
Closed

Computed properties no throws if there is a duplicate #25758

cevek opened this issue Jul 18, 2018 · 7 comments · Fixed by #49848
Labels
Bug A bug in TypeScript
Milestone

Comments

@cevek
Copy link

cevek commented Jul 18, 2018

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%20A%20%3D%20'a'%3B%0D%0Aconst%20x%20%3D%20%7B%5BA%5D%3A%201%2C%20%5BA%5D%3A%201%7D%0D%0A

Related Issues:

@mhegazy mhegazy added the Design Limitation Constraints of the existing architecture prevent this from being fixed label Jul 18, 2018
@mhegazy
Copy link
Contributor

mhegazy commented Jul 18, 2018

Checking for duplicate declaration errors are done earlier in the process, by the time the compiler known the properties it is a bit late to report the errors

@cevek
Copy link
Author

cevek commented Jul 18, 2018

This is very sad

sometimes it works, from time to time

const A = 'a';
const x = {[A]: 1, [A]() {}} // Duplicate declaration '[A]'

@sustained
Copy link

👍 This one is rather annoying for me personally, looking forward to a fix.

@a7madgamal
Copy link

any hacky solution for this?

@a7madgamal
Copy link

a7madgamal commented Mar 15, 2021

found one, for now I will replace Enum.whatever with the value of whatever
this way I get the same enum type safety and also prevent duplicate keys. ugly but works for now :)
My use case is something like this:

type FeatureFlags = {
  [key in FEATURE_FLAGS]: {
    [key in ORG_ALIASES]: { [key in ENVIRONMENT]: boolean };
  };
};

@MickeyPhoenix
Copy link

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'
};

@MickeyPhoenix
Copy link

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 ''.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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants