Warm-up from memory
Write a function that counts completed sessions without printing inside it. Explain the difference between map and filter. Then try converting "" into a number and account for the result.
External input starts as something you do not yet trust to meet your program’s rules. Today our input is a string in the editor; tomorrow it could come from a form. Decide the rule first: a duration must be a whole number from 1 through 240.
Clean surrounding whitespace with trim. Check for empty text before converting: Number treats empty text as zero. Number.isInteger(value) rejects fractional values, NaN, and Infinity. Add range checks to express your application’s rule. Number accepts numeric forms such as 1e2; if your product needs digits only, that is a different parsing rule, not something integer validation guarantees.
Return null when parsing fails, and a number on success. The caller must check that result explicitly. This function accepts strings; passing other types is outside its contract. A precise contract is more useful than a vague claim that it handles everything.
Predict before running
Which inputs fail, and why? After running, try " 30 ", "1.5", and "241".
function parseMinutes(text) {
if (text.trim() === "") {
return null;
}
const value = Number(text);
if (!Number.isInteger(value) || value < 1 || value > 240) {
return null;
}
return value;
}
console.log(parseMinutes("25"));
console.log(parseMinutes(""));
console.log(parseMinutes("five"));Check your prediction
25
null
nullTrace each statement in order. If your prediction differed, describe the first place your mental model and the result diverged before trying again.
Validate before changing state
A parser answers whether text represents an acceptable value. The caller decides how to respond. Keep these jobs separate: returning null lets a form display an error without adding a broken record. Test the edges of a rule, not only a typical input. For a 1–240 limit, try 0, 1, 240, and 241; also try spaces and a decimal.
function parse(text) {
if (text.trim() === "") {
return null;
}
const n = Number(text);
if (!Number.isInteger(n) || n < 1 || n > 240) {
return null;
}
return n;
}
for (const input of ["0", "1", "240", "241", "1.5", " "]) {
console.log(`"${input}" -> ${parse(input)}`);
}Check your prediction
"0" -> null
"1" -> 1
"240" -> 240
"241" -> null
"1.5" -> null
" " -> nullThe quotes around each printed input make otherwise invisible spaces visible. Each input follows the same rule; the checks return early when it fails.
Keep presence, conversion and domain rules separate
There are three questions: was useful text supplied, did it convert to a number, and does that number obey this application’s rule? Combining them carelessly can accept a blank string as zero or a fractional duration as a whole session.
The domain here allows whole minutes from 1 through 240. That choice is stricter than JavaScript’s number type. Make it visible in the validator and test both endpoints. A function returning null for invalid input also requires its caller to check null before using the result.
console.log(Number(""));
console.log(Number("2.5"));
console.log(Number("five"));
console.log(Number.isInteger(2.5));
console.log(Number.isInteger(0));Check your prediction
0
2.5
NaN
false
true Zero is an integer, but this course’s duration rule excludes it. Number.isInteger answers one question only. You still need the presence and range checks to enforce the whole contract.
function parse(text) {
if (text.trim() === "") {
return null;
}
const value = Number(text);
if (!Number.isInteger(value) || value < 1 || value > 240) {
return null;
}
return value;
}
const result = parse("0");
if (result === null) {
console.log("Enter 1–240 whole minutes");
} else {
console.log(result + 5);
}Check your prediction
Enter 1–240 whole minutes The caller does not add five to a rejected result. Choosing null as the failure signal is useful only if the surrounding code respects that branch instead of immediately converting null again.
Try the rule on new inputs
Try “1”, “240”, “241”, “-1”, “2.5” and spaces. Predict the failure rule for each invalid case. Then show the caller preserving a previous valid amount when the new input is rejected.
Your turn
Input Validation: practise
Write cleanTopic(text). Trim spaces, reject empty topics and topics longer than 40 characters by returning null. Otherwise return the cleaned string. Print Loops, then null for a blank topic.
// Write cleanTopic and call it with " Loops " and " ".Hint 1: the idea
Check the cleaned value, not the original text length.
Hint 2: a first step
Save text.trim(), then compare its length to zero and 40.
Show one solution
function cleanTopic(text) {
const topic = text.trim();
if (topic.length === 0 || topic.length > 40) {
return null;
}
return topic;
}
console.log(cleanTopic(" Loops "));
console.log(cleanTopic(" "));Loops
nullReturning null keeps invalid records out of the program. String length counts UTF-16 code units, not necessarily user-perceived characters; this simple limit is sufficient for our practice project, not a universal text rule.
What you should be able to explain
- Why must blank text be checked before conversion?
- List the boundary cases for a different limit of 5–90.
- Who should decide how to display a validation error?
Completion is saved in this browser only. It does not measure mastery.