TypeScript provides several useful utility types, among which Record is particularly valuable for defining an object type where specific keys K are mapped to values of type T. Introduced in TypeScript 2.1, Record is a flexible way to define object types.
1. What is Record?
Record is a utility type that allows specifying the keys of an object using K while ensuring all values conform to the type T.
Basic Syntax
type Record<K extends keyof any, T> = {
[P in K]: T;
};
This is a Mapped Type, where each key P in K is mapped to value of type T.
2. Basic Usage of Record
Basic Example
const httpStatusMessages: Record<number, string> = {
200: "OK",
404: "Not Found",
500: "Internal Server Error",
};
In this example, keys are of type number (representing HTTP status codes), and their corresponding values are of type string.
3. Benefits of Record
(1) Restricting Key Types
type StatusCode = 200 | 404 | 500;
const statusMessages: Record<StatusCode, string> = {
0: 'Unknown', // Object literal may only specify known properties, and '0' does not exist in type 'Record<StatusCode, string>'.
200: "OK",
404: "Not Found",
500: "Internal Server Error",
};
Using an unspecified key results in an error, improving type safety.
(2) Ensuring Type Consistency
type StatusCode = 200 | 404 | 500;
const statusMessages: Record<StatusCode, string> = { // Property '200' is missing in type '{ 404: string; 500: string; }' but required in type 'Record<StatusCode, string>'.
404: "Not Found",
500: "Internal Server Error",
};
All keys must be defined, preventing missing values.
One of the key benefits of Record is that it ensures all specified keys are present in the object. This is because it is implemented as a mapped type, meaning that TypeScript expects every key from K to be explicitly defined.
type StatusCode = 200 | 404 | 500;
const statusMessages: {[key in StatusCode]: string} = {
200: "OK",
404: "Not Found",
// 500 is missing, so TypeScript throws an error
};
This expands into:
type StatusMessagesType = {
200: string;
404: string;
500: string;
};
Since 500 is missing in the object, TypeScript will throw an error stating that the property 500 is required but not provided. This ensures that all possible keys are accounted for, reducing potential runtime errors.
(3) Handling Dynamic Keys
const dynamicData: Record<number, string> = {};
dynamicData[1] = "Hello";
dynamicData[2] = "World";
Keys can be added dynamically, which is a key strength of Record.
4. When to use Alternatives to Record
(1) When Using Constant Objects
Using as const
ensures that values remain literal types, improving type safety.
type StatusCode = 200 | 404 | 500;
const statusMessages = {
200: "OK",
404: "Not Found",
500: "Internal Server Error",
} as const;
statusMessages[200] = "NG"; // Cannot assign to '200' because it is a read-only property.
5. Conclusion
Record is a powerful utility type in TypeScript that ensures uniform key-value relationships. It is especially useful when restricting key types while maintaining type consistency.
Top comments (0)