DEV Community

Md Mostafizur Rahman
Md Mostafizur Rahman

Posted on

Creating a type safe `objectKeys` function

In the world of TypeScript development, encountering the Object.keys function can sometimes lead to a frustrating experience. Consider a scenario where you have an object with keys apple, banana, and cherry. When attempting to iterate over these keys extracted from Object.keys, TypeScript treats the keys as strings. That means that when I try to access it I get this horrible long type error. No index signature with parameter of type string was found in type '{ apple: string; banana: string; cherry: string;}'.

export const fruitBasket = {
  apple: "Apple",
  banana: "Banana",
  cherry: "Cherry"
};

Object.keys(fruitBasket).forEach((key) => {
  console.log(myObject[key]);
});
Enter fullscreen mode Exit fullscreen mode

In this snippet, we're encountering the issue. Even though the keys are apple, banana, and cherry, TypeScript treats them like ordinary strings. This leads to frustrating type-related problems when trying to use these keys to access the actual properties.

So let's build our own objectKeys function that plays well with TypeScript's rules. This custom function uses TypeScript's generics and the keyof operator (which grabs the real key types) to ensure things are typed properly.

function objectKeys<O extends object>(obj: O): (keyof O)[] {
  return Object.keys(obj) as (keyof O)[];
}
Enter fullscreen mode Exit fullscreen mode

Here's what's happening with the function:

  • objectKeys is what we've named our function.
  • <O extends object> is a generic type parameter. It allows us to accept various types of objects while retaining the original type information.
  • (obj: O) is a function parameter named obj with the type O. This means the function can take an object of any type.
  • : (keyof O)[] specifies the return type of the function. It's an array containing keys of type (keyof O).

Now, when we use objectKeys(fruitBasket), each key inside the loop is treated as apple, banana, or cherry.

objectKeys(fruitBasket).forEach((fruit) => {
  console.log(fruitBasket[fruit]);
});
Enter fullscreen mode Exit fullscreen mode

Top comments (0)