How the TypeScript Record Type Works
📣 Sponsor
TypeScript Records are a great way to ensure consistency when trying to implement more complex types of data. They enforce key values, and allow you to create custom interfaces for the values. The TypeScript Record
type was implemented in TypeScript 2.1, and takes the form Record<K, T>
. Let's take a look at how it works.
Utility Types
A Record
is a utility type - that means it is a type especially defined by TypeScript to help with a certain problem. You can learn more about utility types here
How Typescript Record Types Work
Suppose you have a data set which looks like the one below.
const myData = {
"123-123-123" : { firstName: "John", lastName: "Doe" },
"124-124-124" : { firstName: "Sarah", lastName: "Doe" },
"125-125-125" : { firstName: "Jane", lastName: "Smith" }
}
Our data set has an ID for its key, which is of type string
. All of the values have the same format or type - that is, each has two properties: firstName
and lastName
.
For this data structure, a Record
is the best utility type to use to define it's specific type. The Record
type allows us to define a type for both the key
(our ID), and the value
(our firstName
/lastName
object). We can define our Record
type as follows:
type User = {
firstName: string,
lastName: string
}
const myData:Record<string, User> = {
"123-123-123" : { firstName: "John", lastName: "Doe" },
"124-124-124" : { firstName: "Sarah", lastName: "Doe" },
"125-125-125" : { firstName: "Jane", lastName: "Smith" }
}
Any Record
in TypeScript takes the form Record<K, T>
, where K
is the type of the key, and T
is the type of the values. Above, we have defined a new type User
for our values, and set our keys to type string
.
Record Types and Union Types
Sometimes, we can have an object with a predefined set of possible keys. This is particularly true when calling from an API. For example:
const myData = {
"uk" : { firstName: "John", lastName: "Doe" },
"france" : { firstName: "Sarah", lastName: "Doe" },
"india" : { firstName: "Jane", lastName: "Smith" }
}
Let's presume that for our data set above, the key can only be three values: uk, france or india. In this case, we can define a type for User
, and a union type for our key
:
type User = {
firstName: string,
lastName: string
}
type Country = "uk" | "france" | "india";
const myData:Record<Country, User> = {
"uk" : { firstName: "John", lastName: "Doe" },
"france" : { firstName: "Sarah", lastName: "Doe" },
"india" : { firstName: "Jane", lastName: "Smith" }
}
Using this method, we can enforce strict rules about the values the key
is allowed to be, along with the type our values
should conform to. Since this data structure is so common, the Record
utility type is one of the most commonly used utility types in TypeScript.
Conclusion
The Record
type is a powerful tool and one of the most useful utility types available in TypeScript. Understanding how it works is important in understanding TypeScript. For more useful content, check the links below:
- TypeScript is full of other useful utility types like Record. Read about them here.
- New to TypeScript? Check out Google's TypeScript Style Guidelines.
More Tips and Tricks for Typescript
- How the TypeScript Extract Type Works
- How the TypeScript NonNullable Type Works
- How the TypeScript ReturnType Type works
- Type Casting in TypeScript
- Typescript Tuples, and how they work
- How the TypeScript Readonly Type Works
- How Intrinsic Type Manipulations work in TypeScript
- The Difference between TypeScript Interfaces and Types
- How Typescript Generic Types Work
- How TypeScript Conditional Types Work