A string id is not necessarily a usable or unique id. Normalize by trimming first, reject blanks, then check uniqueness across the decoded catalogue. Otherwise “b1” and ” b1 ” can enter as supposedly distinct identities and collide later.
A Set<string> stores unique string values. has checks membership and add records a value. This generic spelling restricts the stored element type; the runtime object is JavaScript’s ordinary Set. The catalogue’s duplicate check runs after row decoding so it sees normalized ids.
A decoder returning Book[] establishes per-row rules and cross-row rules. Keep those promises explicit: finite nonnegative integer pages, nonblank normalized text, and unique ids. TypeScript cannot infer a uniqueness invariant merely from id:string.
The small example below isolates identity policy. Day 7 combines it with the full record decoder and reports the row of the duplicate. Extra input fields are ignored through projection rather than copied into trusted records.
Predict, run, and explain
Write the output and trace the important state changes before checking it. Then run the program. Use Check types first; execution is allowed only when the real compiler accepts the source.
function uniqueIds(ids: readonly string[]): boolean {
const seen = new Set<string>();
for (const raw of ids) {
const id = raw.trim();
if (id === "" || seen.has(id)) {
return false;
}
seen.add(id);
}
return true;
}
console.log(uniqueIds(["a", "b"]));
console.log(uniqueIds(["a", " a "]));Enable JavaScript to edit and type-check this example.
Check your prediction
true
false Normalize before enforcing a cross-row invariant
Primitive field checks establish that each row is shaped correctly. They do not establish that ids are unique across the whole collection. Run relationship checks on normalized domain values, not raw spellings that the decoder will later change.
A Set<string> makes the chosen identity representation explicit. It cannot decide whether ids should be case-sensitive or whether leading spaces are meaningful. State those rules before adding values, and keep duplicate rejection separate from silently dropping duplicates.
function duplicate(ids: readonly string[]): boolean {
const seen = new Set<string>();
for (const raw of ids) {
const id = raw.trim();
if (seen.has(id)) {
return true;
}
seen.add(id);
}
return false;
}
console.log(duplicate(["a", " a "]));
console.log(duplicate(["a", "A"]));Enable JavaScript to edit and type-check this example.
Check your prediction
true
false This policy trims but preserves case. Lowercasing would create a different domain rule and needs deliberate tests rather than a casual cleanup change.
const ids = ["a", "a", "b"];
console.log(new Set(ids).size);
console.log(ids.length);
console.log(new Set(ids).size === ids.length);Enable JavaScript to edit and type-check this example.
Check your prediction
2
3
false The Set can reveal duplicates, but returning its contents would silently accept a shortened list. If the contract rejects duplicate identities, return a failure instead of deduplicated success.
Try the rule on new inputs
Test raw duplicates, padded duplicates, case differences and blanks. Identify which stage rejects each one. Explain why validating every row independently cannot prove the whole collection’s uniqueness.
Your turn
Domain Rules & Identity: practise
Write uniqueIds as above from memory. Test a blank id, normalized duplicates and an empty list, printing false, false, true.
// Normalize before membership checking and reject blank normalized ids.Enable JavaScript to edit and type-check this example.
Hint 1: the idea
A Set only sees the values you actually add to it.
Hint 2: a first step
Trim the current id once, then inspect and add that normalized value.
Show one solution
function uniqueIds(ids: readonly string[]): boolean {
const seen = new Set<string>();
for (const raw of ids) {
const id = raw.trim();
if (id === "" || seen.has(id)) {
return false;
}
seen.add(id);
}
return true;
}
console.log(uniqueIds([" "]));
console.log(uniqueIds(["a", " a "]));
console.log(uniqueIds([]));Enable JavaScript to edit and type-check this example.
false
false
trueExplain why the implementation meets the stated contract. Which part is enforced by the language or checker, and which part needs behavioral evidence?
Change it and test it
Change the implementation to check raw ids before normalization and find a test that fails. Explain whether duplicate titles should be rejected too; that is a different domain decision, not something a generic uniqueness helper should assume.
Completion is saved in this browser only. It does not measure mastery.