Introduction to TypeScript Dictionaries
TypeScript dictionaries let you create type-safe collections of key-value pairs. Whether you're building a cache, storing configuration settings, or managing application state, dictionaries provide a structured way to organize and access data. Let's explore how to work with dictionaries in TypeScript.
Creating a Dictionary in TypeScript
A object type in TypeScript can be created using either the built-in Map<K, V>
object to create an object with string keys or an object with an index signature. Here's how to create one using Map:
const dictionary = new Map<string, number>();
dictionary.set('key', 10);
Alternatively, define an object with an index signature:
const objDictionary: { [key: string]: number } = {};
objDictionary['key'] = 10;
Defining a Dictionary Type in TypeScript
Defining a dictionary type in TypeScript ensures type safety and helps maintain code. Use an interface or the Record<K, V>
type to define a dictionary type. Here's an example with an interface:
interface DictionaryType {
[key: string]: number;
}
const dict: DictionaryType = {};
Or use the Record<K, V>
type:
type DictionaryType2 = `Record<string, number>`;
const dict2: DictionaryType2 = {};
Iterating Over a Dictionary in TypeScript
Iterating over a dictionary in TypeScript is easy. Use a for
loops or the Object.keys()
method to go through the keys of an object. For more complex filtering operations, check out how to write advanced TypeScript filters. Here's an example with a for
loop:
const obj = { key1: 10, key2: 20 };
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
console.log(key, obj[key]);
}
}
Or use the Object.keys()
method with forEach
:
const obj = { key1: 10, key2: 20 };
Object.keys(obj).forEach(key => {
console.log(key, obj[key]);
});
Checking if a Key Exists in a TypeScript Dictionary
To prevent errors, check if a key exists in a TypeScript dictionary before trying to access it. Use the in
operator or the has()
method. Here's how to check using the in
operator:
const obj = { key: 10 };
if ('key' in obj) {
console.log('Key exists');
}
Or use the has()
method with Map<K, V>
:
const map = new Map<string, number>();
map.set('key', 10);
if (map.has('key')) {
console.log('Key exists');
}
Updating Values in a TypeScript Dictionary
Updating values in a TypeScript dictionary is straightforward. Use the set()
method or assign a new value:
const map = new Map<string, number>();
map.set('key', 10);
map.set('key', 20);
Or use direct object property assignment with a key value pair:
const obj = { key: 10 };
obj.key = 20;
Removing Keys from a TypeScript Dictionary
To maintain type safety when modifying dictionaries, use the appropriate removal method for your dictionary type. For Maps, use the delete()
method:
const map = new Map<string, number>();
map.set('key', 10);
map.delete('key');
For object type dictionaries, use the delete
operator:
const obj = { key: 10 };
delete obj.key;
Initializing a TypeScript Dictionary with Default Values
Initializing a dictionary with default values helps set up initial data. Use the Map<K, V>
constructor or an object literal. Here's how with the Map
constructor:
const map = new Map<string, number>([
['key1', 10],
['key2', 20],
]);
Or use default value with object literals:
const obj = {
key1: 10,
key2: 20,
};
Common Challenges and Solutions
Problem: Defining a Dictionary Type with Multiple Value Types
TypeScript dictionaries can handle different types using union types to define flexible value types:
type ValueType = string | number;
const dict: { [key: string]: ValueType } = {};
Or use the Record<K, V>
type with a union:
type DictionaryType = `Record<string, ValueType>`;
const dict2: DictionaryType = {};
Problem: Iterating Over a Dictionary While Maintaining Type Safety
To maintain type safety while iterating over a dictionary, use Object.entries()
with type guards. Here's an example:
const obj = { key1: 'value1', key2: 10 };
for (const [key, value] of Object.entries(obj)) {
if (typeof value === 'string') {
console.log(key, value);
} else if (typeof value === 'number') {
console.log(key, value);
}
}
Problem: Removing Keys Dynamically Without Affecting Type Definitions
Use the Omit<T, K>
type to remove a key from an object type without affecting type definitions. Here's an example:
type OriginalType = { key1: string; key2: number };
type UpdatedType = `Omit<OriginalType, 'key1'>`;
const originalObj: OriginalType = { key1: 'value1', key2: 10 };
const updatedObj: UpdatedType = { key2: 10 };
Working with TypeScript Dictionaries
TypeScript dictionaries give you type-safe key-value storage in your applications. The built-in interface and record types help catch errors at compile time, while methods like Map<K, V>
and object literals provide flexible implementation options.
Key points to remember:
-
Use object type for simple key-value storage
-
Choose Map when you need methods like has() and delete()
-
Take advantage of TypeScript's type checking for safer code
-
Consider performance implications when choosing between Map and object literals
For more details on working with TypeScript in Convex and type safety, check out Convex's TypeScript cookbook.