Object.values and Object.entries are unsound and inconsistent with Object.keys.
See original GitHub issueSearch Terms: Object.values Object.entries sound soundness unsound inconsistent Object.keys
Code Proposed change: https://github.com/MicahZoltu/TypeScript/commit/603c36370c7fdcd142b1493ca8cbbb955db73b69
Back in November 2016, a PR (#12207) was submitted to make the types of Object.entries
and Object.values
generic. This PR was reviewed and accepted, and as a note it was recommended that Object.keys
be updated similarly. The author then submitted a PR to update Object.keys
(#12253) but @ahejlsberg made the very valid point that this change was unsound and the PR was closed. The author of both PRs then suggested that perhaps #12207 should be reverted, but this revert never happened.
This issue is to discuss options for rectifying this situation and I propose we make Object.entries
and Object.values
consistent with the sound behavior of Object.keys
. The major issue here is that this IS a breaking change since people may be relying on the currently unsound behavior of Object.values
and Object.entries
. However, I think having TypeScript be inconsistent on this front indefinitely is not good, and I don’t think changing Object.keys
to be unsound is the right solution, so at the least this change should be merged into TS 4.x.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:32
- Comments:21 (4 by maintainers)
Top GitHub Comments
I think if Typescript is about improving developer experience, Object.keys should return
(keyof T)[]
, it’s easy enough to typecast it to make it bekeyof T
but, there should at least be something likeObject.typeCastedKeys
or something of that ilk.+1 for moving
Object.entries
andObject.values
to the currentObject.keys
behavior. Out of the two, it’s the more sound definition and prevents more unexpected type errors. It also aligns more with how Typescript’s type system works, and forces more people to become aware of object type compatibility.Moving
Object.keys
tokeyof T
provides a false sense of safety, but also doesn’t align with how Typescript’s type system works. Typescript object types declare subsets of every object, not a strict definition of the object’s shape. It’s important for users to understand that any arbitrary object can be a member of an object type, so long as it has the specified fields, and that when iterating over the object’s keys or values, it’s possible for there to be an infinite number of keys in addition to the specified ones. Accessing properties on an object is safe, but iterating over object properties may produce an unexpected and unsafe result.Typescript is not a language for improving your editor’s autocomplete, it’s a language for preventing type errors. Given how Typescript’s type system works, it’s safer to use an
unknown
values type and astring[]
key type because those are correct. Again, any arbitrary object can be assigned to another type because of how type compatibility works. The alternative not only gives users a false sense of security, but also encourages misconceptions about how Typescript’s type system works.