Typescript: Object.keys should return `keyof T`

Created on 10 Jul 2019  路  6Comments  路  Source: microsoft/TypeScript


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

Most helpful comment

It鈥檚 because it sounds so obvious that I just checked the open issues before opening this one 馃槄 Nobody expects keyof to be different from keys()

All 6 comments

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

Duplicate and rejected multiple times: https://github.com/microsoft/TypeScript/pull/12253#issuecomment-263132208, #30314, #13254. #30228, #28899, #28284, #26901, #30749, #31087.

more info

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

@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).

It鈥檚 because it sounds so obvious that I just checked the open issues before opening this one 馃槄 Nobody expects keyof to be different from keys()

Was this page helpful?
0 / 5 - 0 ratings

Related issues

seanzer picture seanzer  路  3Comments

dlaberge picture dlaberge  路  3Comments

uber5001 picture uber5001  路  3Comments

kyasbal-1994 picture kyasbal-1994  路  3Comments

jbondc picture jbondc  路  3Comments