Search code examples
typescriptmapped-types

How to use map types to define a type for `Object.keys`?


I want to define a more strict Object.keys function using typescript mapped types.

Example:

Let's say I have an object defined with const:

const myObj = {
  a: 'some value',
  b: 5
};

When I use Object.keys on this object, the returning type is string[]

const keysOfMyObj = Object.keys(myObj); // `const keysOfMyObj: string[]`

Question:

Instead, I'd like this type to be more specific. Instead of returning the type string[], I'd prefer if Object.keys returned the type ("a" | "b")[].

Desired type:

const newKeysOfMyObj = myKeys(myObj); // `const newKeysOfMyObj: ("a" | "b")[]`

What I've tried:

I think this can be accomplished using typescript mapped types.

I've defined a type that asserts a type is an object's values are the same as the keys:

type Keys<T> = {
  [P in keyof T]: P;
};

let myObjKeysOnly: Keys<typeof myObj>;

// resulting type:
// ```
// let myObjKeysOnly: {
//   a: "a";
//   b: "b";
// }
// ```

I've tried to implement this function as just a typed wrapper over Object.keys:

function myKeys<T>(obj: T) {
  return Object.keys(obj) as (Keys<T>);
}

Any ideas?


Solution

  • You can use keyof :

    function myKeys<T>(obj: T): keyof T[] {
      return Object.keys(obj) as any;
    }
    
    const x = myKeys({ a: 123, b: 123 });
    

    More

    Moving types : https://basarat.gitbooks.io/typescript/content/docs/types/moving-types.html