A correct signature cannot prove that unsubscribe removes anything. A runtime test should register observable callbacks, perform cleanup, publish, and compare the actual calls. Testing only return types misses that defect completely.
Use controlled synchronous steps here; no timers are needed. Duplicate registration, mutation during dispatch, disposal and thrown listener identity are distinguishable public behaviors. Each test should explain the rule it would fail if the implementation changed.
Projection also needs runtime evidence. An object typed as a smaller payload can still contain private fields; the decoder must create a clean object. Compare keys and verify the original input is unchanged. Readonly is useful for callers but does not freeze JavaScript values.
When a lesson says a test protects a rule, deliberately break that rule once. The authoring checks mutate the downloaded project’s trimming, unsubscribe, snapshot and disposal implementation, then require its targeted test to fail. More passing assertions are not a substitute for a distinguishing failure.
Predict, check, and run
Write the output before running. Use Check types first, then Check & run. Types disappear at runtime: explain both what the compiler checks and what the code actually does. Each editor is an independent ES module; await asynchronous work explicitly.
const input = { title: " Types ", secret: "private" };
const output = { title: input.title.trim() };
if ("secret" in output || input.title !== " Types ") {
throw new Error("Projection failed");
}
console.log("projection verified");Enable JavaScript to edit and type-check this example.
Check your prediction
projection verified Make a passing assertion distinguish a real regression
A final value can look right even when the implementation violates ownership or call-count rules. Observe independent effects: input data, returned data, listener invocations and state after cleanup. Each assertion should target a stated public promise.
Mutation practice is useful only when the test fails for the intended behavioral reason. A syntax error proves nothing about coverage. Use a valid but wrong implementation, such as replacing token deletion with a no-op or iterating a live collection instead of a snapshot.
const records = new Set<{ callback: () => void }>();
let calls = 0;
const callback = () => {
calls++;
};
const first = { callback };
const second = { callback };
records.add(first);
records.add(second);
records.delete(first);
for (const record of [...records]) {
record.callback();
}
console.log(calls);Enable JavaScript to edit and type-check this example.
Check your prediction
1 The same function remains through the second independent subscription. A Set of functions would not represent both registrations and would fail a contract allowing duplicate subscriptions.
const source = { title: " Types ", secret: true };
const result = { title: source.title.trim() };
console.log(result.title);
console.log(source.title === " Types ");
console.log("secret" in result);Enable JavaScript to edit and type-check this example.
Check your prediction
Types
true
false Normalization, nonmutation and projection are three distinct runtime properties. A smaller static annotation or one success assertion would not prove them all.
Try the rule on new inputs
For each project runtime group, name a valid mutation it should catch. Check both a normal result and the input or lifetime effect that could be wrong while the result still looks right.
Build it yourself
Runtime Contract Tests: practise
Write a tiny subscribe/publish helper with independent token records. Register the same callback twice, remove one, publish, and assert the count is exactly one. Print cleanup verified. Do not assert private Set size.
// Start from the stated contract. Add a valid call and an edge case.Enable JavaScript to edit and type-check this example.
Hint 1: the idea
Observe callback effects through the public functions.
Hint 2: a first step
Use a counter captured by the listener and compare it after publish.
Show one solution
const records = new Set<{ callback: () => undefined }>();
function subscribe(callback: () => undefined): () => void {
const token = { callback };
records.add(token);
return () => {
records.delete(token);
};
}
function publish(): void {
for (const token of [...records]) {
token.callback();
}
}
let count = 0;
const callback: () => undefined = () => {
count++;
};
const remove = subscribe(callback);
subscribe(callback);
remove();
remove();
publish();
if (count !== 1) {
throw new Error("Independent cleanup failed");
}
console.log("cleanup verified");Enable JavaScript to edit and type-check this example.
cleanup verifiedTrace the implementation against the task before comparing styles. A passing example supports that case; use the changes below to challenge the wider contract.
Change it and test it
Replace cleanup with a no-op and confirm this assertion fails. Then store callbacks directly instead of token records and observe why duplicate registration needs another test. Restore the stated contract.
Completion is saved in this browser only. It does not measure mastery.