Skip to content
Back to TypeScript for Clearer Code course

Work & Development · Frontend Frameworks & TypeScript

Free preview

Describe values and understand inference

Lesson 1 of TypeScript for Clearer Code. Anyone can read this lesson with no account. Every lesson after this one is for students.

Describe your data

Run a small TypeScript file and explain inferred types, written types and runtime checks.

Your goal: Run a small TypeScript file and explain inferred types, written types and runtime checks.

1Types describe expectations

Complete Build Applications with React first. Several lessons here refer to your learning-goal tracker from that course, and the last module adds TypeScript to it.

JavaScript runs in the browser or Node. TypeScript checks the kinds of values your code expects, then produces JavaScript. Think of labels on classroom boxes: a label saying "numbers" helps catch an object put in the wrong box, but it does not turn a word into a number. An annotation is a type you write down. Inference is a type TypeScript works out from the code. A passing check is useful evidence about your code, but data arriving while the app runs still needs its own checks.

Create a separate type-lab folder, open a terminal in it and run npm init -y, then npm install --save-dev --save-exact typescript@7.0.2. TypeScript 7 is the current major version, rewritten as a native program so it checks code much faster than 5.x; every example in this course was checked with 7.0.2. If an older tutorial shows TypeScript 5 or 6, the language features in this course work the same way. Keep package-lock.json and use npm ci for later installs. The TypeScript handbook explains inference and annotations independently of a particular editor.

Save this complete example as data.ts. Compile with npx tsc data.ts --strict --target ES2022 --module commonjs --outDir build, then run node build/data.js. Compiling means turning the TypeScript source into JavaScript. Executing means running that JavaScript. They are two separate steps.

export {};
const goalTitle = 'Practice keyboard navigation';
let completedSessions = 2;
const sessionMinutes: number = 25;
function plannedMinutes(sessions: number, minutes: number): number {
  return sessions * minutes;
}
const total = plannedMinutes(completedSessions, sessionMinutes);
console.log(`${goalTitle}: ${total} minutes`);
completedSessions += 1;
console.log(plannedMinutes(completedSessions, sessionMinutes));

Expected output: Practice keyboard navigation: 50 minutes, followed by 75. TypeScript infers a string for the title and a number for the changing session count. The explicit sessionMinutes annotation communicates a deliberate numeric expectation. The function's parameter and return types make the input/output contract visible.

Now temporarily assign the string 'two' to completedSessions. The checker should reject the assignment. Repair it before executing again. If an older build still runs after a failed check, you are observing previously JavaScript produced by the compiler, not proof that the new source passed. For checks that must not produce output, use --noEmit. For this compile-and-run lab, add --noEmitOnError when comparing successful and failed builds.

2Independent practice and investigation

  1. Write a function that turns a minutes estimate into a sentence. Its result should be a string.
  2. Write a function that calculates an average from several session lengths. Its result should be a number.
  3. Decide and document what the average function returns for an empty list.
  4. Write the expected results for each function before running it, then compare the actual results.

Deliberately remove an annotation and inspect the inferred type in your editor. Then change a function to return either a number or a sentence. Explain why a mixed return type makes the caller's job harder. Choose a consistent contract rather than silencing the warning with any.

3Check yourself

  1. Does the number annotation round decimals?
  2. Does type checking validate a downloaded JSON payload?
  3. Should every local variable have an annotation?
Show answers
  1. No, number includes ordinary JavaScript numeric values and does not enforce whole minutes.
  2. No, an external value still needs runtime checks.
  3. No: clear inference often avoids redundant code, while public boundaries benefit from explicit signatures.

4Project milestone

In your learning-goal tracker, identify three values and two function boundaries whose intended types you can explain. Record one mistake caught by the lab checker, including the checker's error message and the corrected reasoning. Keep these notes as the beginning of your feature-migration evidence; do not convert the whole application at once.

Continue with the full course

This free preview is lesson 1 only. Enroll to open the rest of TypeScript for Clearer Code.