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

Object.keys should return `keyof T` #32321

Closed
bfred-it opened this issue Jul 10, 2019 · 6 comments

Comments

Projects
None yet
5 participants
@bfred-it
Copy link

commented Jul 10, 2019

TypeScript Version: 3.6.0-dev.20190717

Code

const feature = {
	description: '',
	screenshot: '',
	disabled: ''
};

const list = Object.keys(feature);

Expected behavior:

keys<T extends object>(o: T): Array<keyof T>;
typeof list = Array<"description" | "screenshot" | "disabled">

Actual behavior:

keys(o: {}): string[];
typeof list = string[]

Workaround:

const feature = {
	description: '',
	screenshot: '',
	disabled: ''
};

const list = Object.keys(feature) as Array<keyof typeof feature>;

Playground Link: https://www.typescriptlang.org/play/#src=const%20feature%20%3D%20%7B%0D%0A%09description%3A%20''%2C%0D%0A%09screenshot%3A%20''%2C%0D%0A%09disabled%3A%20''%0D%0A%7D%3B%0D%0A%0D%0Aconst%20keys%20%3D%20Object.keys(feature)%3B

@j-oliveras

This comment has been minimized.

Copy link
Contributor

commented Jul 10, 2019

@AnyhowStep

This comment has been minimized.

Copy link
Contributor

commented Jul 10, 2019

Object.keys() does not return (keyof T)[] in the general case.

In some specific instances, it will. In most others, it will not.

declare const x : { a : number };
Object.keys(x);

You might expect the above to return ["a"] but it's possible for it to return ["a", "b"], too.

Because {a: number, b: number} is assignable to {a: number}


If anything, we can only say Object.keys() returns keyof T if,

  • We have no number keys
  • We have no symbol keys
  • keyof T does not contain keys from types in the parent and ancestor [[prototype]]
  • T does not have optional properties
  • T is some kind of "strict" object that does not allow extra properties (TS doesn't have such a concept at the moment)

I'm sure there are other constraints I haven't thought of.

[Edit]
Oh. The linked Stack Overflow answer explains it better

@MartinJohns

This comment has been minimized.

Copy link

commented Jul 10, 2019

Duplicate and rejected multiple times: #12253 (comment), #30314, #13254. #30228, #28899, #28284, #26901, #30749, #31087.

more info

@bfred-it bfred-it closed this Jul 10, 2019

@RyanCavanaugh

This comment has been minimized.

Copy link
Member

commented Jul 10, 2019

Maybe we should make a template just for this. It'd save people a lot of time.

@MartinJohns

This comment has been minimized.

Copy link

commented Jul 10, 2019

@RyanCavanaugh I actually just copied my last comment and added the other issue. But this is a good candidate for the FAQ (but I doubt it's being checked before).

@bfred-it

This comment has been minimized.

Copy link
Author

commented Jul 11, 2019

It’s because it sounds so obvious that I just checked the open issues before opening this one 😅 Nobody expects keyof to be different from keys()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.