If you're a TypeScript user then you've probably come across Utility Types. They are very useful and increase the readability and reusability of your code. The TypeScript Record type mostly is used to create an object type with specified keys/values, and define a type for a collection of objects or to define the shape of an object.

Today I'm going to show you Record Utility Type with examples of how to use it in your projects.

Let's say we have an app where the user can order food 🥙 from a complete stranger and we show this food in 2 different ways. Some of the products are immediately available, while others are yet to go on sale and have the coming soon label. Below I've attached an overview image of what these list items might look like.

Element available:

They look a little different, one has a box with information at the bottom, while the other has a box with information at the top, a darkened image, and the COMING SOON text.

We can program the display of these items in the simplest way using lots of ifs, creating very ugly, unusable code that no one will want to touch later. 🤢 What if we suddenly have to add a food type like unavailable or sold out. It would be a disaster.

Also, either that crap or... we can use Record! Creating a reusable, easily extensible code that when someone sees it they will be in tears of delight 😍

You may also like: Flask vs. Django - which framework to choose?

How TypeScript Record Types work?

Let's start with the definition from the documentation.

Record - constructs an object type whose property keys are keys and whose property values are typed. This utility can be used to map the properties of a type to another type.

And an example:

interface CatInfo {
	age: number;
	breed: string;
}

type CatName = "miffy" | "boris" | "mordred";

const cats: Record<CatName, CatInfo> = {
	miffy: { age: 10, breed: "Persian" },
	boris: { age: 5, breed: "Maine Coon" };
	mordred: { age: 16, breed: "British Shorthair" },
};

cats.boris;

In the documentation, they show us that we can use the TypeScript Record Utility Type to create an object that contains cat names as keys, and requires CatInfo type data as values for those keys.

This means that every object I find in the cats object must consist of the cat's name and information about that cat, throughout the object we have a data match, provided in a very clean and simple way.

We can achieve even better results when we use ENUM for this!

Let's go back to the example with the food list 🤓

We declare ENUM with the names of our categories for displaying items in the food list.

enum FoodListTypes {
	available = 'AVAILABLE',
	comingSoon = 'COMING_SOON',
}

Then the enum will be able to be extended with more entries.

Next, we retrieve our FoodList component, which has all the logic for displaying the food list in a particular way.

import {FoodList} from '../components'

And we declare the possible variants of FoodList, namely AvailableFoodList and ComingSoonFoodList:

const AvailableFoodList = (list: Food[]) => <FoodList 
	type={FoodListTypes.available} list={list} />
const CoomingSoonFoodList = (list: Food[]) => <FoodList 
	type={FoodListTypes.comingSoon} list={list} />

Our plan is to create a code that allows us, by entering only a specific password from ENUMA, to select the appropriate FoodList variant. And this is where Record 💥 comes into action.

Let's look at the code below:

const FoodLists: Record<FoodListTypes, (list: Food[]) => JSX.Element> = {
	[FoodListTypes.available]: AvailableFoodList,
	[FoodListTypes.comingSoon]: ComingSoonFoodList,
}

We create a FoodLists object that contains all possible FoodList variants. We give it a Record type, we give as a key the enum entries - FoodListTypes, and as values to the keys, we give a function that returns the appropriate list. It is so simple! 

Such code is incredibly easy to extend and we can easily add new FoodList types, as well as remove them!

You might be interested: Dive into Javascript deeper with an explanation of Object.Prototype and classes

Now we can use the FoodLists object to display the list currently selected by the user:

const CurrentFoodList = () => {
	const [currentFoodListType, setCurrentFoodListType] = useState(FoodListTypes.available)
	const [list, setList] = useState<Food[]>([])

	useEffect(() => {
		setList(useStore(currentFoodListType))
	}, [currentFoodListType, setCurrentFoodListType])


	return (
		<>
			<button onClick={() => setCurrentFoodListType(FoodListTypes.available)}>
      	Order
      </button>
			<button onClick={() => setCurrentFoodListType(FoodListTypes.comingSoon)}>
      	Coming Soon
      </button>

			[renderFoodList(list, currentFoodListType)}
		<>
	)
}

🤯 We have a simple component that displays two buttons and renders the currently selected list. The food list is retrieved on the fly from the stock based on the currently selected type to display, and the currently selected food type is selected by clicking on the appropriate button.

The Benefits of Using TypeScript Record Type

The TypeScript Record type provides several benefits for developers, including:

1. Type safety: Thanks to the possibility to define a type for a collection of objects with a specific set of keys/values developers can ensure type safety and catch errors at compile time, rather than at runtime.

2. Improved readability: Using Record to define the shape of an object can make your code more readable and easier to understand. It can also help to reduce the amount of code you need to write, by defining the object type with a single line of code.

3. Simple maintenance: By defining the object type using Record, you can make your code easier to maintain over time. If you need to change the shape of an object, you only need to update the Record definition, rather than searching through your code for every instance of the object.

4. Code reuse: Record types can help you define a type that can be reused in multiple parts of your codebase, reducing the amount of duplication and making your code more modular.

5. Flexible and extensible: The Record type allows you to define object types with any combination of keys/values that makes it a powerful tool for working with complex data structures.

Overall, the Record type in TypeScript is a robust tool for those who looks to define object types with a specific set of keys/values, as well as facilitate common type transformations. It can help to ensure type safety, improve code readability and maintainability, and make your code more modular and reusable.

TypeScript Record Type – conclusion

I hope I've helped you get familiar with an interesting use of one of the Utility Types and that you won't be afraid to use it in your projects. With Record, we can easily make code reusable and easily extensible.

If you want to learn even more from me, I invite you to codingbrah.com 😎