Challenge 1: Build a Generic hasProperties — Possible Solution ==================================================================== function hasProperties( obj: unknown, ...keys: K[] ): obj is Record { if (typeof obj !== "object" || obj === null) { return false; } return keys.every((key) => key in obj); } // --- Usage --- function handle(value: unknown) { if (hasProperties(value, "id", "email", "createdAt")) { // value is narrowed to Record<"id" | "email" | "createdAt", unknown> console.log(value.id, value.email, value.createdAt); } else { console.log("Missing one or more required fields"); } } handle({ id: 1, email: "a@b.com", createdAt: "2026-01-01" }); // logs all three handle({ id: 1, email: "a@b.com" }); // logs the else branch — missing createdAt handle(null); // logs the else branch — not an object at all // A single-key call still works, since ...keys accepts any number of arguments: if (hasProperties(value, "id")) { console.log(value.id); } WHY THIS WORKS -------------- - `...keys: K[]` accepts any number of property-key arguments — calling with one key behaves like the chapter's single-key hasProperty, and calling with several behaves like a proper multi-key check, without needing two separate functions. - `keys.every((key) => key in obj)` only returns true if EVERY given key exists on the object — a single missing key correctly fails the whole check, same as a hand-written `"id" in obj && "email" in obj && ...` chain would, but without repeating the `in` check per field. - The return type `obj is Record` means every key passed in is known to exist on `obj` inside the narrowed branch, with each key's value typed as `unknown` (since hasProperties has no way to know the actual value types) — callers still need their own narrowing or validation for the values themselves.