Dictionaries in TypeScript: From Chaos to Order (A Complete Guide with Code)
\n\nImagine you are writing an application for learning English. You need to store word translations: "cat" → "cat", "dog" → "dog". What is the best way to organize this data? Of course, use a Dictionary — a data structure where each key is unique and associated with a value.
In JavaScript, dictionaries are implemented through regular objects or Map. But TypeScript adds powerful typing, turning chaotic collections into strict, predictable structures. In this article, we will cover declaration and initialization of Dictionary in TypeScript from simple to complex. You will learn how to avoid common mistakes and write code that works predictably.
What is a Dictionary in TypeScript? (And why it's not just an object)
\n\nIn programming, a Dictionary is a collection of key-value pairs. In TypeScript, you can create it in three main ways:
\n\n- \n
- Object with an index signature (
{ [key: string]: T }) \n - Record — a utility type \n
- Map — a built-in ES6 class \n
Each approach has its own advantages and nuances. Let's break them down with real examples.
\n\nMethod 1: Classic object with an index signature
\n\nThe most popular way to declare a dictionary in TypeScript is to use an index signature. This tells the compiler: "The object can have any number of properties with keys of a specific type".
\n\n// Declare a dictionary type where the key is a string and the value is a number\ninterface DictionaryNumber {\n [key: string]: number;\n}\n\n// Initialization\nconst ages: DictionaryNumber = {\n "Anna": 25,\n "Peter": 30,\n "Elena": 28\n};\n\n// Adding a new element\nages["Olga"] = 35;\n\nconsole.log(ages["Anna"]); // 25\n\nImportant: TypeScript requires that all values match the declared type. Attempting to add a string will cause a compilation error:
\n\n// Error! Type 'string' is not assignable to type 'number'\nages["Olga"] = "thirty five";\n\nWhen to use this approach?
\n- \n
- When you need a simple and fast dictionary \n
- When keys are strings or numbers \n
- For small collections (up to 1000 elements) \n
Method 2: Record — elegant syntax
\n\nTypeScript provides a built-in utility type Record<K, V>. It creates an object type where all keys have type K and values have type V.
// Declaration and initialization in one line\nconst grades: Record<string, number> = {\n "Mathematics": 5,\n "Physics": 4,\n "History": 5\n};\n\n// You can use an enum for keys\nenum Subject {\n Math = "math",\n Physics = "physics",\n History = "history"\n}\n\nconst gradesBySubject: Record<Subject, number> = {\n [Subject.Math]: 5,\n [Subject.Physics]: 4,\n [Subject.History]: 5\n};\n\nAdvantages of Record:
\n- \n
- Concise syntax \n
- Good readability \n
- Support for union types for keys \n
Method 3: Map — for advanced scenarios
\n\nThe Map class from ES6 is a full-fledged key-value collection with additional capabilities. In TypeScript, it is typed using generics:
// Declaring a Map\nconst userRoles: Map<string, string> = new Map([\n ["admin", "Administrator"],\n ["user", "User"],\n ["guest", "Guest"]\n]);\n\n// Adding\nuserRoles.set("moderator", "Moderator");\n\n// Retrieving\nconsole.log(userRoles.get("admin")); // "Administrator"\n\n// Checking existence\nif (userRoles.has("user")) {\n console.log("Role exists");\n}\n\n// A