Extending the Planner

The Course
•
4 min read

Add a remainingMinutes field to the planner report. It should total the minutes of incomplete sessions. A feature touches several places: the Report type declares the new promise, summarize computes it, callers display it, and tests verify it.

Start by changing the type, then follow the diagnostics. A return object missing the new field should fail checking. This is useful guidance about where the contract is incomplete, but it cannot tell you whether your new arithmetic implements the correct rule.

Keep the original completedCount and completedMinutes behavior. Do not rename completedMinutes to totalMinutes while changing its meaning; callers may rely on the original contract. A report can contain both completed and remaining work with clearly named fields.

Test empty input, all-completed input, all-incomplete input and a mixed list. Include zero minutes so your code does not confuse a valid value with absence. If an input is malformed, it belongs in parser tests rather than being patched inside summarize.

This is a small example of a general workflow: state the rule, adjust the type contract, implement the behavior, review compiler diagnostics, test runtime results, and explain the change. You do not need a sophisticated generic abstraction for a three-field report.

Predict, check, then run

Before running, write down the output and explain which information the checker knows. Click Check types first, then Check & run.

Predict, then runTypeScript
const sessions = [
  { minutes: 25, done: true },
  { minutes: 40, done: false }
];
let remaining = 0;

for (const session of sessions)
  if (!session.done) {
    remaining += session.minutes;
  }

console.log(remaining);

Enable JavaScript to edit and type-check this example.

Check your prediction
40

Add a new fact without changing existing meanings

Remaining minutes is a new report fact, not a new meaning for completedMinutes. Compute a tiny fixture’s expected fields by hand before editing Report. Compiler diagnostics can locate missing construction sites, but cannot prove the arithmetic or ownership policy. Use unequal durations and include zero so a count-based or truthy-default mistake becomes visible.

Boundary or caseWhat to inspect
EmptyAll totals are zero
All incompleteCompleted stays zero and remaining sums every duration
MixedExisting completed behavior survives the new field

Update the Report type, summarize, its caller and tests as one feature. Re-run the old assertions too. Decide whether derived data belongs in a report or stored state, and name the extra consistency rule if you store it.

Your turn

Exercise

Extending the Planner: practise

Write a typed summarize returning completedMinutes and remainingMinutes from readonly session records. Print 25 and 40 for a mixed list, then 0 for an empty list’s remainingMinutes. In the downloaded capstone, keep completedCount too.

Your workspaceTypeScript
// Declare the return shape before implementing the two branches.

Enable JavaScript to edit and type-check this example.

Hint 1: the idea

Every session contributes to one of two totals based on done.

Hint 2: a first step

Initialize both totals to zero inside the function.

Show one solution
One possible solutionTypeScript
type Session = {
  minutes: number;

  done: boolean;
};

type Report = {
  completedMinutes: number;

  remainingMinutes: number;
};

function summarize(sessions: readonly Session[]): Report {
  let completedMinutes = 0;
  let remainingMinutes = 0;

  for (const session of sessions) {
    if (session.done) {
      completedMinutes += session.minutes;
    } else {
      remainingMinutes += session.minutes;
    }
  }

  return { completedMinutes, remainingMinutes };
}

const report = summarize([
  { minutes: 25, done: true },
  { minutes: 40, done: false }
]);

console.log(report.completedMinutes);
console.log(report.remainingMinutes);
console.log(summarize([]).remainingMinutes);

Enable JavaScript to edit and type-check this example.

25
40
0

Explain the types at the function boundary and the runtime checks, if any. Compare your approach before copying this answer.

Change it and explain it

Add assertions for all-completed and all-incomplete lists. If extending the local capstone, update model.ts, the message in main.ts and tests.mjs. Explain which missing changes the compiler caught and which required a runtime expectation.

Was this article helpful?

Your response is saved on this device.