TypeScript Tutorial
TypeScript Project: Contact Book
Store contacts in a Map from name to number, then add, find, and list them.
What you will build
A contact book maps a name to a phone number. The type is Map<string, string>: the key is the name, the value is the number. You add entries, look one up, and list every pair. A Map keeps insertion order, so the list follows the order you added names, not alphabetical order.
Names and numbers are hardcoded. Compile with Try it in TypeScript at/typescript/try.
Insert with a key
Create the Map with new Map<string, string>(). set(name, number) creates the key or replaces the number. That is the add-or-update operation. get(name) reads a number, orundefined if the name is missing.
Example
const book = new Map<string, string>();
book.set("Ada", "555-0101");
book.set("Lin", "555-0144");
console.log(book.get("Ada"));
console.log(book.get("Lin"));Output is Ada’s number, then Lin’s. The keys are strings; the values are strings.
Find without guessing
get returns undefined for a missing name. It does not insert a blank entry. Still check with has(name) before you print, so a miss is a clear message instead of the wordundefined.
Example
function findContact(book: Map<string, string>, name: string): void {
if (!book.has(name)) {
console.log(name + " not found");
return;
}
console.log(name + ": " + book.get(name));
}
const book = new Map<string, string>();
book.set("Ada", "555-0101");
findContact(book, "Ada");
findContact(book, "Omar");After the has check, get is safe to print. Omar is not in the book, so you get the not-found line. Unlike a plain object, looking up a missing Map key does not create a ghost contact.
Try this in /typescript/try with Try it in TypeScript. If you skiphas and print book.get("Omar") directly, the output is undefined.
List in insertion order
A for...of on a Map visits [key, value] pairs. The first item is the name. The second is the number. TypeScript’s Map keeps insertion order, so the visit order matches the order you calledset for new keys.
Example
const book = new Map<string, string>();
book.set("Nia", "555-0199");
book.set("Ada", "555-0101");
book.set("Lin", "555-0144");
for (const [name, number] of book) {
console.log(name + " " + number);
}You inserted Nia first. The print order is Nia, Ada, Lin.
Complete contact book
Helpers wrap add, find, and list. Add overwrites an old number for the same name, which is how you update a contact. The file seeds three people, updates one number, looks up two names, then lists the book.
Example
function addContact(book: Map<string, string>, name: string, number: string): void {
book.set(name, number);
}
function findContact(book: Map<string, string>, name: string): void {
if (!book.has(name)) {
console.log("Find " + name + ": not found");
return;
}
console.log("Find " + name + ": " + book.get(name));
}
function listContacts(book: Map<string, string>): void {
console.log("Contacts (" + book.size + ")");
for (const [name, number] of book) {
console.log(name + " " + number);
}
}
const book = new Map<string, string>();
addContact(book, "Ada", "555-0101");
addContact(book, "Lin", "555-0144");
addContact(book, "Omar", "555-0170");
addContact(book, "Lin", "555-0202");
findContact(book, "Lin");
findContact(book, "Nia");
listContacts(book);Lin’s number is the updated 555-0202. Nia is not found. The list has three rows in insertion order: Ada, Lin, Omar. Updating Lin did not move that row; the key already existed.
Common mistakes
- Using a plain object
{ }and then iterating withfor...in. A Map is the type this project asks for, and it does not mix in inherited keys. - Expecting alphabetical order. TypeScript’s Map is insertion order. If you need sorted names, collect the keys and sort them before you print.
- Using two parallel arrays for names and numbers. A Map keeps one number per name without a search loop.
- Forgetting that keys are case-sensitive.
adais notAda.
Practice
- Change Lin’s updated number from 555-0202 to 555-0333 and confirm find and list both show the new value.
- Add a fourth contact named Nia and confirm find now succeeds and the list grows to four rows.
- Refuse to add a contact whose name is an empty string, and count how many numbers start with
555-.
Next project: turn numeric scores into letter grades and an average.