TypeDrop
2026-02-24 Challenge
2026-02-24
Easy
Typed Contact Book Lookup
You're building a small contact book utility for an internal HR tool. Given a list of contacts with varying optional fields, you must build a strongly-typed lookup index and implement search/filter helpers — the challenge is in the types, not the logic.
Goals
- Define `ContactIndex`, `ContactSummary`, and `SearchFilters` using the `Record`, `Pick`, and `Partial` built-in utility types respectively.
- Implement `buildIndex` to convert a `Contact[]` into a `ContactIndex` keyed by each contact's `id`.
- Implement `summarise` to extract only the `id`, `name`, `email`, and `department` fields from every contact in a `ContactIndex`.
- Implement `filterContacts` to return contacts matching ALL provided filter fields, with special subset-matching logic for the optional `tags` array.
challenge.ts
/** The department a contact belongs to. */
type Department = "engineering" | "design" | "marketing" | "hr" | "finance";
/** A contact's role seniority. */
type Seniority = "junior" | "mid" | "senior" | "lead" | "manager";
interface Contact {
id: string;
name: string;
email: string;
department: Department;
seniority: Seniority;
phone?: string;
tags?: string[];
}
// Your job: define these three types using built-in utility types...
type ContactIndex = Record<string, Contact>; // TODO: use Record<>
type ContactSummary = Pick<Contact, "id" | ...>; // TODO: use Pick<>
type SearchFilters = Partial<Contact>; // TODO: use Partial<>
// ...then implement these three functions:
function buildIndex(contacts: Contact[]): ContactIndex { ... }
function summarise(index: ContactIndex): ContactSummary[] { ... }
function filterContacts(contacts: Contact[], filters: SearchFilters): Contact[] { ... }
Hints (click to reveal)
Hints
- For `filterContacts`, iterate over the keys of the `filters` object with `Object.keys` — but remember each value may be `undefined` (Partial!), so skip those keys entirely.
- When checking `tags`, `Array.prototype.every` paired with `Array.prototype.includes` is your friend for verifying that all filter tags exist on the contact.
- The `Pick` utility type takes a type and a union of string literal keys: `Pick<Contact, 'id' | 'name'>` — make sure you only name the four required fields for `ContactSummary`.
Useful resources
Or clone locally
git clone -b challenge/2026-02-24 https://github.com/niltonheck/typedrop.git