In TypeScript, for efficient data structuring, storage and retrieval, we use data structures and mapped types. The Record and Map are among the most commonly used types for managing collections of data. Both have their own strengths, use cases, and characteristics.
This article explores the syntax, provides simple examples, and outlines the differences between Record and Map types. This knowledge will help us in using these constructs effectively and make more informed decisions.
1. Introduction to Record and Map
Let us begin with a simple introduction to each construct and a simple example. Later we will delve into their differences.
1.1. Record Type
The Record type enables us to define precise object shapes with specific key-value types. It exists as an additional type, such as classes or interfaces, to encapsulate data & behavior and ensure type safety for the object’s structure.
Note that the primary difference between Class and Record is that records are used for modeling structured data with a consistent format whereas classes are created to encapsulate data and behavior and offer inheritance, encapsulation, and polymorphism.
In the following example, we declare a new type named Person of type Record which declares the shape of the Person objects. In this case, the keys of the object are of type string, and the values can be either of type string or number.
type Person = Record<string, string | number>;
The following code declares a constant variable named alice
with the type Person. This means that alice
must adhere to the structure defined by the Person type. Then we initialize the alice
object with concrete values of the keys.
const alice: Person = {
name: "Alice",
age: 30,
};
1.2. Map Data Structure
Contrary to a Record which is a type, a Map is a full-fledged data structure for storing the key-value pairs. It provides dedicated methods for adding, retrieving, and deleting entries from the Map.
Unlike object types such as Record, a Map can store any type of value including objects, functions, and other primitives.
We can create a new Map instance using the Map constructor.
let myMap = new Map<string, number>();
Then we can add, update or delete entries from the Map using its inbuilt methods.
myMap.set("Lokesh", 37);
myMap.set("Raj", 35);
//Get value by key
let age = myMap.get("Lokesh"); // age = 37
//Check entry by Key
myMap.has("Lokesh"); // true
//Delete entry by key
let isDeleted = myMap.delete("Lokesh");
2. Difference between Record and Map
Now that we have a basic understanding of both types, let us identify their differences:
Feature | Record | Map |
---|---|---|
Type Annotation | Defines object shapes with specific key-value types. | Standard data structure to store key-value pairs with varying types. |
Data Storage | Emphasizes structured data representation. | Focuses on dynamic data storage and retrieval. |
Keys | Uses string literals as keys. | Supports keys of any data type. |
Value Types | All values must have the same type. | Values can be of different types. |
Built-in Methods | Lacks built-in iteration methods. | Provides built-in methods for adding, retrieving, and iterating the entries. |
Order of Insertion | Order of properties not guaranteed. | Maintains the insertion order of entries. |
Use Cases | Suitable for structured data definitions. | Ideal for storing dynamic data in the form of key-value pairs. |
3. When to use?
Let’s explore some practical examples of when to use Map
and Record
in TypeScript.
3.1. Use Record for Structured Data
Record
is particularly useful when we want to define a specific structure for an object with string keys and a consistent value type, and it doesn’t require the dynamic behavior of methods or additional functionality.
For example, in a video player app, users can configure their playback settings, such as volume, subtitles, and playback speed. These settings always adhere to a well-defined structure, and often we don’t need methods to mutate their content.
type PlaybackSettings = Record<string, string | number | boolean>;
class VideoPlayer {
private settings: PlaybackSettings = {};
updateSettings(key: string, value: string | number | boolean): void {
this.settings[key] = value;
}
getSettings(): PlaybackSettings {
return { ...this.settings };
}
}
const player = new VideoPlayer();
player.updateSettings("volume", 70);
player.updateSettings("subtitles", true);
console.log(player.getSettings());
// Output: { volume: 70, subtitles: true }
3.2. Use Map to store Dynamic Data
We should use Map
when we need to store dynamic key-value pairs, especially if we require the support of built-in methods for adding and manipulating the collection of data.
For example, a user is adding random items to his/her shopping cart. In this case, we can store the item IDs as Map keys, and item quantities as Map values. The built-in methods will immensely help in keeping the data in sync when a user adds or removes new items or existing items from his cart. Keeping such data in Map helps in managing items in the cart, in more simpler way.
class ShoppingCart {
private cartItems: Map<string, number> = new Map();
addItemToCart(itemID: string, quantity: number): void {
if (this.cartItems.has(itemID)) {
const currentQuantity = this.cartItems.get(itemID)!;
this.cartItems.set(itemID, currentQuantity + quantity);
} else {
this.cartItems.set(itemID, quantity);
}
}
removeItemFromCart(itemID: string, quantity: number): void {
if (this.cartItems.has(itemID)) {
const currentQuantity = this.cartItems.get(itemID)!;
const newQuantity = Math.max(currentQuantity - quantity, 0);
if (newQuantity === 0) {
this.cartItems.delete(itemID);
} else {
this.cartItems.set(itemID, newQuantity);
}
}
}
getCartContents(): Map<string, number> {
return new Map(this.cartItems);
}
}
const userCart = new ShoppingCart();
userCart.addItemToCart("item001", 2);
userCart.addItemToCart("item002", 1);
userCart.addItemToCart("item001", 1); // Adding more of an existing item
4. Conclusion
As discussed in the article, both Record
and Map
serve distinct purposes and offer unique advantages based on the specific usecases. The Record
type shines when we want to define a specific structure for objects with string keys and consistent value types. On the other hand, the Map
data structure excels in dynamic data storage and manipulation scenarios.
Happy Learning!!
Comments