Technology

Apptension Blog

How to use TypeScript Record Utility Type? Detailed guide

Hey, what's up 🤙?

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 and values. It is often used to 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 go!

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 beautiful, 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 and 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 type of an object with a single line of code.
  3. Simple maintenance: By defining the type of an object 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 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 and 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 and 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 😎

Thank you for your attention and cheers!

Read more

SaaS implementation types, best practices, benefits and fails
7 US best telemedicine apps to follow in 2023
Kacper Szarkiewicz
Kacper Szarkiewicz
Frontend developer
Ready to bring your product vision to life?

Partner with our experienced development team today.
Get in touch

How to use TypeScript Record Utility Type? Detailed guide

February 9, 2023
5
minutes read
audio description available
TL;DR

If you're a TypeScript user then you should know about Utility Types - readability and reusability friends of your code. In this article, we're showing you Record Utility Type with examples of how to use it in your projects.

0:00
0:00
How to use TypeScript Record Utility Type? Detailed guide
How to use TypeScript Record Utility Type? Detailed guide

Hey, what's up 🤙?

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 and values. It is often used to 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 go!

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 beautiful, 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 and 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 type of an object with a single line of code.
  3. Simple maintenance: By defining the type of an object 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 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 and 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 and 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 😎

Thank you for your attention and cheers!

Kacper Szarkiewicz
Kacper Szarkiewicz
Frontend developer
Download our free e-book
Learn various stories about startups, SaaS, and IT straight from founders, CEOs, and directors and get 2023 industry insights collected in one nifty e-book 🚀