The download has two test layers. contracts.ts contains four intentional invalid usages under @ts-expect-error and is included in normal compiler checking. catalogue.test.mjs runs the emitted JavaScript to verify normalization, issue paths, duplicate ids, state transitions and async dependency failures.
Run npm test after installing the pinned compiler. Its build step checks the type contracts before running five grouped runtime cases. Do not execute the emitted contracts.js file; it contains deliberately invalid operations that only exist as compile checks.
Challenge both layers. Removing readonly from pages should make a negative directive unused and fail the compiler. Removing duplicate-id validation or the request-id comparison should still compile but fail runtime tests. Restore every mutation afterward.
The schedule group connects the actual createLoader and reduce exports. It allocates ids before awaiting, then releases old/new transports in both orders. Old success and old failure must leave the current loading or ready state unchanged. This checks orchestration as well as individual reducer transitions.
The test strategy is intentionally small: it checks this library’s advertised behavior without snapshots of implementation internals. A new public feature needs corresponding evidence, not just more type aliases.
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.
type Result<T> =
| {
ok: true;
value: T;
}
| {
ok: false;
message: string;
};
function read(result: Result<number>): number | null {
return result.ok ? result.value : null;
}
if (read({ ok: true, value: 0 }) !== 0) {
throw new Error("Zero lost");
}
if (read({ ok: false, message: "bad" }) !== null) {
throw new Error("Failure lost");
}
console.log("2 runtime cases passed");Enable JavaScript to edit and type-check this example.
Check your prediction
2 runtime cases passed Connect direct transition tests to full request schedules
Decoder tests protect field truth; reducer tests protect transitions for already constructed actions. The schedule group connects real loaders and reducer calls so request ids survive actual awaiting. Keep these layers separate when interpreting coverage. A stale-result test after ready does not replace the case where a newer request is still loading.
| Boundary or case | What to inspect |
|---|---|
| Positive normalized data | Check projected output and unchanged source |
| Invalid field or duplicate | Reject with a specific path rather than partial success |
| Old and new completion | Cross both orders with old success and old failure |
For each deliberate mutation, name its distinguishing assertion before changing source. Then weaken readonly and explain why the negative consumer should fail even when the same runtime fixtures still pass. Restore and rebuild between experiments.
Your turn
Testing the Public Contract: practise
Write a typed function that returns a copied record with trimmed title. Assert the original text stays padded, the result is trimmed and an unrelated input field is not copied. Print projection verified.
// The return shape is not sufficient evidence; compare actual runtime data.Enable JavaScript to edit and type-check this example.
Hint 1: the idea
An explicit new object controls projection and ownership.
Hint 2: a first step
Construct only the modeled title property after trimming it.
Show one solution
type Book = { title: string };
function clean(book: Book): Book {
return { title: book.title.trim() };
}
const source = { title: " Types ", privateNote: true };
const result = clean(source);
if (
result.title !== "Types" ||
source.title !== " Types " ||
"privateNote" in result
) {
throw new Error("Projection failed");
}
console.log("projection verified");Enable JavaScript to edit and type-check this example.
projection verifiedExplain 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
Run all project cases before changing source. Then introduce each documented mutation and identify the layer that catches it. Explain why a type test may pass while data validation is wrong, and why runtime tests cannot prove a public signature rejects an invalid TypeScript caller.
Completion is saved in this browser only. It does not measure mastery.