Intro
Ensuring type safety with TypeScript is essential when accessing object properties within your application. One powerful yet overlooked feature that can simplify this process is the keyof typeof
construct. This simple trick leverages the keyof
and typeof
operator to infer the key types of an object at runtime. As a result, it helps you write safer, more maintainable code and reduces the risk of passing invalid property names.
What is keyof
?
keyof
is a TypeScript operator used to return the union type of keys from an object type
In the following example, the keyof
operator lets us define constraints on which property names can be passed into our function:
type Document = {
id: number,
title: "string,"
author: string
}
type DocumentKeys = keyof Document // returns "id" | "title" | "author"
const myDocument = {
id: "0",
title: "\"Untitled Document\","
author: "Robbie"
}
function getMyDocumentProperty(key: DocumentKeys){
return myDocument[key]; // key must be either "id", "title", or "author"
// thanks to keyof, no other property name is allowed
}
TypeScript will throw an error if key
is anything other than "id", "title", or "author".
What is typeof
?
In TypeScript, the typeof
operator returns the type value of the variable, object, or function that follows it.
We can use typeof to automatically infer the type of an object without manually defining it:
const document = {
id: 0,
title: "Untitled Document",
author: "Robbie"
}
type Document = typeof document; // { id: number, title: string, author: string }
Combining keyof typeof
Combining the two operators allows us to dynamically extract an object's keys in a type-safe manner. But when would we need this in practice?
Consider the following scenario:
- You have predefined an object with key-value pairs, such as a configuration object
- You are building a React component, and one of its
props
must correspond to a key in this predefined object
This is where combining keyof
and typeof
really shines.
Instead of manually defining the object keys as a union type — which can lead to errors if keys change — you can use keyof typeof
to derive the keys directly from the object.
Here’s an example where I leveraged this technique in one of my reusable UI components:
// --- Button.tsx ---
type ButtonProps = {
text: string;
twStyles?: string;
color: keyof typeof colors;
onClick?: () => void;
};
const colors = {
primary:
"transition-2s hover-translate-y rounded-lg border-2 border-[#004A7C] bg-[#004A7C] px-4 py-2 text-white hover:border-[#31678c] hover:font-semibold hover:bg-[#31678c]",
secondary:
"transition-2s hover-translate-y rounded-lg border-2 border-[#004A7C] bg-gray-50 px-4 py-2 text-[#004A7C] hover:font-semibold hover:bg-[#eaf3ff]",
};
function Button({ text, twStyles, color = "primary", onClick }: ButtonProps) {
const colorStyles = colors[color] || "";
return (
<button
onClick={onClick}
className={`${twStyles} ${colorStyles} rounded-lg border-2 px-4 py-2`}
>
{text}
</button>
);
}
export default Button;
In this example, keyof typeof
ensures the color
prop is restricted to valid keys of the colors
object. If colors
is updated, its type automatically reflects the changes, reducing the risk of bugs.
Conclusion
There you have it! Understanding the keyof typeof
combo in TypeScript allows you to create type-safe, maintainable code that adapts to changes in your objects. This approach eliminates redundant type definitions and reduces the chance of errors, making it a valuable tool for any TypeScript developer.
What did you think?
I’d love to hear your thoughts! Have you ever used this technique? If so, how? Share your feedback in the comments below!
Top comments (0)