DEV Community

Dharan Ganesan
Dharan Ganesan

Posted on

Day 40: keyof

What is keyof?

The keyof operator in TypeScript is used to create a union type of all the property names (keys) of an object type. This union type can then be used to define and enforce type constraints within your code.

type KeyOfDemo = keyof { name: string; age: number }; // "name" | "age"
Enter fullscreen mode Exit fullscreen mode

How does it work?

When applied to an object type, keyof generates a union type comprising all the keys of that object's properties. This union type can be used for various purposes like indexing, type-checking, and creating more precise type definitions.

2. Practical Use Cases

Type-Safe Object Access

One of the most common use cases for keyof is enabling type-safe object access. Consider a scenario where you have an object representing a person:

const person = {
  name: "John",
  age: 30,
  city: "New York",
};
Enter fullscreen mode Exit fullscreen mode

By using keyof, you can create a type that ensures you only access valid properties:

type Person = typeof person;
type PersonKeys = keyof Person; // "name" | "age" | "city"
Enter fullscreen mode Exit fullscreen mode

Now, you can access person properties safely:

function getProperty(obj: Person, key: PersonKeys): any {
  return obj[key];
}

const name = getProperty(person, "name"); // ✅ Type-safe
const invalid = getProperty(person, "gender"); // ❌ Compile-time error
Enter fullscreen mode Exit fullscreen mode

Enforcing Property Keys

You can also use keyof to enforce that an object contains specific keys:

function hasRequiredKeys(obj: Person, keys: ["name", "age"]): boolean {
  return keys.every(key => key in obj);
}

const hasKeys = hasRequiredKeys(person, ["name", "age"]); // ✅ true
const missingKey = hasRequiredKeys(person, ["name", "gender"]); // ❌ false
Enter fullscreen mode Exit fullscreen mode

Function Parameter Validation

keyof can be a valuable tool for validating function parameters, ensuring only valid keys are accepted:

function updatePerson(obj: Person, key: PersonKeys, value: any): void {
  obj[key] = value; // ✅ Type-safe
}

updatePerson(person, "age", 31); // ✅
updatePerson(person, "gender", "Male"); // ❌ Compile-time error
Enter fullscreen mode Exit fullscreen mode

3. Advanced Techniques

Combining keyof with Other Operators

You can combine keyof with other TypeScript operators for even more powerful type definitions. For example, using keyof with typeof to create a mapped type:

type OptionalPerson = {
  [K in keyof Person]?: Person[K];
};
Enter fullscreen mode Exit fullscreen mode

Generics and keyof

Generics and keyof can be used together to create flexible and reusable type-safe functions:

function getPropertyByKey<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

const cityName = getPropertyByKey(person, "city"); // ✅ Type-safe
Enter fullscreen mode Exit fullscreen mode

4. Common Pitfalls and Best Practices

Avoiding String Literals

Avoid using string literals when working with keyof to maintain type safety:

const prop = "age";
const age = person[prop]; // ❌ No type checking
Enter fullscreen mode Exit fullscreen mode

Type Narrowing

Remember that keyof unions need to be narrowed down for conditional checks:

type KnownKeys = "name" | "age";
function isKnownKey(key: string): key is KnownKeys {
  return ["name", "age"].includes(key);
}
Enter fullscreen mode Exit fullscreen mode

Keyof in Libraries

When working with external libraries, be cautious about assuming property keys. Libraries might use techniques like symbol-based keys, which keyof might not cover.

Top comments (1)

Collapse
 
jxdjxd profile image
jxd

so clear