Combine a numeric check with a result type. Your caller needs either a valid number of minutes or a readable error. A discriminated union can express that relationship without optional fields floating independently.
This task starts with a string, as a form input would. Use ordinary JavaScript conversion: Number(text). An empty or whitespace-only string converts to zero, so check blank text separately. Number.isFinite(value) returns true only for a finite numeric value; it rejects NaN and both infinities without converting strings. This is slightly different from JavaScript beginner’s integer check: our rule here allows zero and finite decimals, while that form exercise required whole minutes from 1 through 240. These are different product rules, not a change caused by TypeScript. Reject negative values too; the number annotation alone cannot do it.
Use { kind: "ok"; minutes: number } for success and { kind: "error"; message: string } for failure. A display function should inspect kind before reading the matching field. Do not force a result into one branch with an assertion.
Budget your time for edge cases, not just the first happy-path input. A parser that handles “25” but silently accepts a blank form has not met the brief. Type checking verifies that you return a valid variant; runtime checks decide which variant is truthful.
Predict, check, then run
Before running, write down the output and explain which information the checker knows. Click Check types first, then Check & run.
const blank = " ";
console.log(Number(blank));
console.log(Number.isFinite(Number("oops")));
console.log(Number("25"));Enable JavaScript to edit and type-check this example.
Check your prediction
0
false
25 Acceptance cases before you code
Write a small test plan before implementing expected result alternatives. These cases extend the brief; they are not a second worked solution. Predict the expected behavior independently, then test through the public function. A good ordinary example and a good boundary example should catch different possible mistakes.
| Case to try | What your result should demonstrate |
|---|---|
| Numeric text zero | Return the success variant |
| Blank or negative input | Return the specified failure variant |
| Success branch rendering | Use the discriminant so zero remains a valid result |
After the core task passes, deliberately break one rule and identify the case that notices it. Restore the implementation and explain the failure in terms of the contract, not the number of assertions. If a case requires a concept you have not recalled, revisit the relevant lesson before opening the solution.
Your turn
Checkpoint: Parse Minutes: practise
Implement parseMinutes(text: string) returning the Result union described above. Blank, non-finite and negative inputs return message “Invalid minutes”. Valid inputs, including zero, return ok. Print 25 min, 0 min and Invalid minutes for “25”, “0” and ” ”.
// Define Result, parseMinutes, and a display function. Test three inputs.Enable JavaScript to edit and type-check this example.
Hint 1: the idea
Check the raw text for blankness before converting it.
Hint 2: a first step
Store Number(text) in a local variable, then check finiteness and the lower bound.
Show one solution
type Result =
| {
kind: "ok";
minutes: number;
}
| {
kind: "error";
message: string;
};
function parseMinutes(text: string): Result {
const minutes = Number(text);
if (text.trim() === "" || !Number.isFinite(minutes) || minutes < 0) {
return { kind: "error", message: "Invalid minutes" };
}
return { kind: "ok", minutes };
}
function describe(result: Result): string {
if (result.kind === "ok") {
return `${result.minutes} min`;
}
return result.message;
}
console.log(describe(parseMinutes("25")));
console.log(describe(parseMinutes("0")));
console.log(describe(parseMinutes(" ")));Enable JavaScript to edit and type-check this example.
25 min
0 min
Invalid minutesExplain the types at the function boundary and the runtime checks, if any. Compare your approach before copying this answer.
Change it and explain it
Test “oops”, “Infinity”, “-1” and “2.5”. The stated contract permits finite decimals. If the product needs whole minutes, add Number.isInteger and update the contract. Explain what the compiler proves about Result and what your conditions prove about minutes.
Completion is saved in this browser only. It does not measure mastery.