Ever ran into errors in TypeScript and it took you hours to figure out?, that was me recently while building a personal project. In this article, I want to go over how I solved a TypeScript problem in my React application using one of TypeScript's pre-defined types.
While working on one of my personal projects, I ran into a TypeScript error that got me confused. I had a component that rendered a list of tasks grouped by the date they were added, the tasks were coming in as a prop called taskslist
which is an object, and I converted that object into an array using Object.entries()
so I can loop over it and display each task on the screen.
const Todos = ({ taskslist }) => { return ( <> {Object.entries(taskslist).map(([date, tasks], index) => ( <section key={index}> <TodoHeader date={date} noOfTasks={tasks.length} /> <div> {tasks.map((task, index) => ( <TodoItem key={index} task={task} /> ))} </div> </section> ))} </> ); };
Everything worked at runtime, but I kept getting this error from TypeScript
// unknown being tasks Property 'length' does not exist on type 'unknown'.
TypeScript didn’t know tasks
was an array because Object.entries() returns data in the form [string, any][]
or [string, unknown][]
if in strict mode, so the compiler couldn’t infer that tasks had a length property or a map method.
The Solution
After making some research and analyzing my code, I realized the problem wasn’t Object.entries itself, but that I never explained to TypeScript the shape of taskslist. To fix this, I needed to be explicit about how taskslist is defined, that’s when I discovered the Record
type.
What is Record?
Record is a built-in utility type in TypeScript. It's a cleaner way of specifying how the shape of an Object looks when we have keys and values that are predictable. It's syntax looks like this:
Record<KeyType, ValueType>
It basically says:
I want an object whose keys are of type KeyType, and whose values are of type ValueType.
For example:
type UserRoles = Record<string, string>; const roles: UserRoles = { alice: "admin", bob: "editor", };
This is equivalent to writing:
type UserRoles = { [key: string]: string; };
Applying Record to My Problem
In my case, I wanted taskslist to be an object where:
- The keys are strings representing dates like "2025-09-16".
- The values are an array of tasks.
So I defined my types like this:
type Task = { id: number; title: string; ... }; type TodosProps = { taskslist: Record<string, Task[]>; };
then updated my component:
const Todos = ({ taskslist }: TodosProps) => { return ( <> {Object.entries(taskslist).map(([date, tasks], index) => ( <section key={index}> <TodoHeader date={date} noOfTasks={tasks.length} /> <div> {tasks.map((task, index) => ( <TodoItem key={index} task={task} /> ))} </div> </section> ))} </> ); };
Now, TypeScript instantly knew that tasks
was of the type Task[]
, and hence, gave no more errors about length or map.
I liked this solution because it provided me with 3 things
Clarity – Anyone reading the code, including me, can immediately understand the shape of taskslist.
Safety – If I accidentally try to pass in the wrong type, TypeScript will catch it.
Reusability – I can reuse the Task
type in other parts of my app without duplication.
Conclusion
Learning about Record
felt like unlocking a small but powerful superpower in TypeScript. Instead of fighting the compiler, I was able to guide it with the right information, and it rewarded me with better type safety and cleaner code.
If you’ve ever run into a situation where TypeScript doesn’t understand the shape of an object, give Record
a try, it might be the missing piece that makes your app work as expected.
I am oyinkansola, a frontend developer helping productivity coaches build clean websites and tools that make their work easier. You can connect with me on LinkedIn and X.
What's that one TypeScript type that helped you solve a problem?
Top comments (0)