Understanding TypeScript Object.entries Type Safety with Generic Types

Just a guy who loves to write code and watch anime.
Search for a command to run...

Just a guy who loves to write code and watch anime.
No comments yet. Be the first to comment.
Qualities that make outstanding builders.

Bipedal vs quadrupedal: how many legs This is about the number of legs the creature walks on. Bipedal. Two legs. Humans, ostriches, T-rex, kangaroos, most fantasy humanoids. Quadrupedal. Four legs. Do

Intro You hear "lerp" and "smoothstep" everywhere in game dev. They sound like math jargon. They're not. Both are small tools that do the same job: smoothly move from one value to another. The problem

What is Kinematics Kinematics is the math field. It's the study of how things move without worrying about forces (which would be dynamics). FK and IK are the two branches: forward kinematics and inver

Intro Textures are usually the biggest cost in a 3D scene. Memory, bandwidth, and load time all get eaten by them. Resizing them is the obvious lever. There's more. This post is about the less obvious

When using Object.entries() in TypeScript, we lose the relationship between keys and their value types.
For example:
type User = {
age: number;
name: string;
active: boolean;
}
// TypeScript gives us [string, any][]
// We want [('age' | 'name' | 'active'), (number | string | boolean)][]
const entries = Object.entries(user)
But even worse, we lose the specific relationships. We can't be sure that when we have the 'age' key, we get a number.
We can create a type that preserves these relationships:
type Entries<T> = Array
{
[K in keyof T]: [K, T[K]]
}[keyof T]
>
Let's break down how this works:
[K in keyof T] - Maps over each key in T
[K, T[K]] - Creates a tuple of the key and its value type
[keyof T] - Indexes into the mapped type to create a union
Array<...> - Makes it an array of these tuples
type User = {
age: number;
name: string;
active: boolean;
}
// Now TypeScript knows:
// If key is 'age', value is number
// If key is 'name', value is string
// If key is 'active', value is boolean
const entries = Object.entries(user) as Entries<User>
for (const [key, value] of entries) {
if (key === 'age') {
// TypeScript knows value is number
console.log(value + 1)
}
if (key === 'name') {
// TypeScript knows value is string
console.log(value.toUpperCase())
}
}
This pattern is particularly useful when:
Building type-safe APIs
Working with configuration objects
Processing data with specific key-value relationships
Creating generic utility functions
This solution showcases several advanced TypeScript features:
Mapped types for transforming each property
Tuple types for key-value pairs
Indexed access types to get value types
Array types with unions
By combining these features, we maintain type safety while working with object entries.