It seems there are (at least) two definitions of the term "key" within the specification that are not differentiated/explicitly defined.
The most common definition is summarised as: an object property identifier of type string or symbol.
For discussion I'll call this pid (for property ID).
The other definition is more traditional: a string that serves to identify an object in a hash table/map.
For discussion I'll call this hid (for hash table ID).
Where this generates confusion relates to the common usage of an object as a key/value store. In that use case a key is a hid. In all other use cases a key is a pid. This ambiguity is propagated throughout the language itself, with some functions on Object using one definition and others using the other without remark.
Some examples of Object functions that use pid (those that include symbol keys):
- assign: Assigns all properties including symbols
- create: Second param defines properties, including symbol properties
- defineProperty and defineProperties: self-explanatory
- seal: also seals symbol properties
Some examples of Object functions that use hid:
- keys: Only returns keys that are of type string
- entries: Only returns key-value pairs where the keys are strings
- values: Only returns values whose keys are strings
The above lists cover a good number of functions but they're not exhaustive.
Note that the documentation for those three functions on MDN states that all enumerable properties are included, but this is not the case. It's necessary to read the spec to see that these functions only include string keys currently (which is unrealistic to expect from everyone, however desirable).
For convenience this MDN page links to all functions on Object: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
Aside from the MDN documentation this has also caused confusion for the Typescript contributors (which is how I became aware of the problem):
Difficulty deciding on the correct type of the return value of Object.keys: microsoft/TypeScript#12253 (comment)
Ambiguity causing the TS keyof keyword to be implemented using the hid definition of a key rather than the pid definition. Any change to which would now cause breaking changes to all Typescript programs: microsoft/TypeScript#20721 and microsoft/TypeScript#21983
In short it seems that the dual use of Object as both a hash table and as the base "object" type has generated (and will likely continue to generate) confusion because it's so easy to overlook.
For specifics with references to a few relevant parts of the ECMA specification itself see my comment on this issue here: microsoft/TypeScript#21983 (comment)
One potential solution would be to support overloading of the indexing operator in classes, add this to Map and change the hid functions of Object to pid functions. However that would not be backwards compatible so I'm not really sure how this could be resolved? We may be stuck with it indefinitely but at least the spec can be updated to caution on the ambiguity?
It seems there are (at least) two definitions of the term "key" within the specification that are not differentiated/explicitly defined.
The most common definition is summarised as: an object property identifier of type string or symbol.
For discussion I'll call this pid (for property ID).
The other definition is more traditional: a string that serves to identify an object in a hash table/map.
For discussion I'll call this hid (for hash table ID).
Where this generates confusion relates to the common usage of an object as a key/value store. In that use case a key is a hid. In all other use cases a key is a pid. This ambiguity is propagated throughout the language itself, with some functions on Object using one definition and others using the other without remark.
Some examples of Object functions that use pid (those that include symbol keys):
Some examples of Object functions that use hid:
The above lists cover a good number of functions but they're not exhaustive.
Note that the documentation for those three functions on MDN states that all enumerable properties are included, but this is not the case. It's necessary to read the spec to see that these functions only include string keys currently (which is unrealistic to expect from everyone, however desirable).
For convenience this MDN page links to all functions on Object: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
Aside from the MDN documentation this has also caused confusion for the Typescript contributors (which is how I became aware of the problem):
Difficulty deciding on the correct type of the return value of Object.keys: microsoft/TypeScript#12253 (comment)
Ambiguity causing the TS keyof keyword to be implemented using the hid definition of a key rather than the pid definition. Any change to which would now cause breaking changes to all Typescript programs: microsoft/TypeScript#20721 and microsoft/TypeScript#21983
In short it seems that the dual use of Object as both a hash table and as the base "object" type has generated (and will likely continue to generate) confusion because it's so easy to overlook.
For specifics with references to a few relevant parts of the ECMA specification itself see my comment on this issue here: microsoft/TypeScript#21983 (comment)
One potential solution would be to support overloading of the indexing operator in classes, add this to Map and change the hid functions of Object to pid functions. However that would not be backwards compatible so I'm not really sure how this could be resolved? We may be stuck with it indefinitely but at least the spec can be updated to caution on the ambiguity?