Uh oh!
There was an error while loading. Please reload this page.
[fix] ES5 Object.keys only accepts an object - #27089
[fix] ES5 Object.keys only accepts an object#27089Ryan Cavanaugh (RyanCavanaugh) merged 1 commit into
Conversation
Heya Jordan Harband (@ljharb)! Looks like our baselines might need to be updated - it's likely the symbol baselines are printing out a different type for uses of Additionally, is there a reason why |
Jordan Harband (ljharb)
commented
Sep 14, 2018
Daniel Rosenwasser (@DanielRosenwasser) yes, because the spec for Object.keys changed in ES2015 to no longer throw on non-nullish primitives (numbers, strings, booleans, symbols) - so while a type of Thanks, I'll update the tests shortly. |
7a74838 to
7e89a05CompareJordan Harband (ljharb)
commented
Sep 14, 2018
Tests updated. |
Ryan Cavanaugh (RyanCavanaugh)
commented
Sep 17, 2018
Is there an associated bug for this? |
Jordan Harband (ljharb)
commented
Sep 17, 2018
Ryan Cavanaugh (@RyanCavanaugh) no, i didn't file one - it seemed like this would be faster. If you need me to file one that copy-pastes the first two lines in the OP, i can certainly do that. |
Jordan Harband (ljharb)
commented
Oct 19, 2018
ping - does this really need an issue, or is it ready to go as-is? |
7e89a05 to
8b95922CompareJordan Harband (ljharb)
commented
Oct 29, 2018
Uh oh!
There was an error while loading. Please reload this page.
47fd1d4 to
e830f52CompareJordan Harband (ljharb)
commented
Jan 22, 2019
hm, test failures seem unrelated |
Uh oh!
There was an error while loading. Please reload this page.
Jordan Harband (ljharb)
commented
Feb 3, 2019
Ryan Cavanaugh (@RyanCavanaugh) yay, how soon is "soon"? :-D |
e830f52 to
bc43904CompareJordan Harband (ljharb)
commented
Mar 26, 2019
Ryan Cavanaugh (@RyanCavanaugh) any update? |
bc43904 to
0b0ca1eCompareRyan Cavanaugh (RyanCavanaugh)
commented
Mar 26, 2019
Jordan Harband (@ljharb) the reason we ask for an associated issue is that the issue is how we track whether or not we decide we want a PR for something in the first place. I think it's a broadly open question whether calling e.g. |
Uh oh!
There was an error while loading. Please reload this page.
Jordan Harband (ljharb)
commented
Mar 27, 2019
Ryan Cavanaugh (@RyanCavanaugh) sure, that's fine; there's no harm in closing the PR if you don't decide you want the change. However, I'd argue it's not about "sensical" - it's allowed by the spec, and it was explicitly changed in ES6 because people pass primitives into The primary issue is that the ES5 types are incorrect - they currently allow passing non-object non-nullish primitives, but ES5 disallowed this, and only ES2015 enabled that. |
Ryan Cavanaugh (RyanCavanaugh)
commented
Mar 29, 2019
We've had this discussion on Twitter already 😉 I think this is fine to merge once the failing tests gets fixed. |
a08fb56 to
b3c7a62CompareJordan Harband (ljharb)
commented
Mar 30, 2019
Tests should now be fixed. |
After a longer discussion than expected on the merits of |
Jordan Harband (ljharb)
commented
Apr 1, 2019
I opened this because it’s a bug, because i do it this way on purpose in qs, a very well-used library. I’m disappointed in this outcome. |
Jordan Harband (ljharb)
commented
Apr 1, 2019
Ryan Cavanaugh (@RyanCavanaugh) it’s also worth noting - what’s in master does not agree with your decision, because you have the ES5 types as the empty interface. The correction is to make es5 object and es6+ the empty interface. In other words, what you want is what I’m asking for es5 to do, and what you don’t want is what typescript already does. |
I think that when this was discussed at the backlog slog, we misunderstood the topic. I'm sorry about that. The root of the problem is that any sort of change sort of needs to build up its worth, especially when there's some risk of breakage or new conceptual overhead. Regardless of the eventual change, creating the distinction between ES5/ES2015 seems like it would be confusing (i.e. having an overload for You already saw the opposite approach - we erroneously assumed the type already was |
Jordan Harband (ljharb)
commented
Apr 2, 2019
My intention here was for those targeting es5 to be able to get warning of a runtime exception before it happens. Without this PR, the type system will allow it, but an ES5 runtime will not. |
Ryan Cavanaugh (RyanCavanaugh)
commented
Apr 2, 2019
Jordan Harband (@ljharb) This is what I see in the PR and what we were basing our discussion off of: I don't see any part of the PR that adds an |
Uh oh!
There was an error while loading. Please reload this page.
Ryan Cavanaugh (RyanCavanaugh)
commented
Apr 2, 2019
I'm OK taking the PR in its intended form 😉 |
a7eed53 to
9867d8aCompareJordan Harband (ljharb)
commented
Apr 2, 2019
Thanks, sorry for all the back-and-forth. PR updated. |
Ryan Cavanaugh (RyanCavanaugh)
commented
Apr 23, 2019
Jordan Harband (@ljharb) looks like you need to run |
9867d8a to
f1bcc80CompareJordan Harband (ljharb)
commented
Apr 23, 2019
Ryan Cavanaugh (@RyanCavanaugh) oops, thanks. Done! |
Ryan Cavanaugh (RyanCavanaugh)
commented
May 14, 2019
This broke VS Code |
Ryan Cavanaugh (@RyanCavanaugh) can you elaborate? #31380 (comment) implies it caught a bug in vscode, not broke it. |
Ryan Cavanaugh (RyanCavanaugh)
commented
May 14, 2019
Jordan Harband (ljharb)
commented
May 14, 2019
Ryan Cavanaugh (@RyanCavanaugh) ah, gotcha. that suggests a bug in type narrowing then :-) thanks for the followup. |
Ryan Cavanaugh (RyanCavanaugh)
commented
May 14, 2019
Let's say you have code like this declarefunctionkeys(obj: object): string[];functionfn<Textendsnull|object>(arg: T){// Point 1if(!arg)return;// Point 2if(typeofarg!=="object")return;// Point 3keys(arg);}There's an error here because To get the "correct" answer for the type of We'd need #22348 or its equivalent to track this. |
Jordan Harband (ljharb)
commented
May 15, 2019
That seems excessively valuable given that truthiness and falsiness are both core and idiomatic mechanisms used for runtime guards. Hopefully that could land soon, and type narrowing improved? |
Ryan Cavanaugh (RyanCavanaugh)
commented
May 15, 2019
It's not that we don't recognize the value of it, believe me 😉 |

ES5 Object.keys throws on non-objects: http://www.ecma-international.org/ecma-262/5.1/#sec-15.2.3.14 - which is type
object.ES2015 Object.keys allows any "object coercible", ie any non-null non-undefined value - which is
{}: http://www.ecma-international.org/ecma-262/6.0/#sec-object.keysThis attempts to fix the types.
'Bug' or 'help wanted' or is in the Community milestone
masterbranchjake runtestslocallyThis is my first PR to TypeScript; if you can point me to where I should add unit tests, I'll be happy to do so.