beginner18 min

Why Types? From JavaScript to TypeScript

What a type system buys you, and how TypeScript catches a bug that JavaScript happily runs.

What you'll learn

  • Explain what a static type system checks, and when it checks it
  • Annotate a variable with an explicit type
  • Predict whether a given assignment will be rejected by the compiler

Explanation

JavaScript checks almost nothing before your code runs. This function looks fine:

function applyDiscount(price, percent) {
  return price - price * (percent / 100);
}

Call it as applyDiscount("20", 10) and JavaScript does not complain. It converts, guesses, and hands back NaN — "not a number" — which then flows into a total, then into a receipt, and surfaces days later as a support ticket. The mistake happened at the call site; the symptom appeared somewhere else entirely. That distance is what makes these bugs expensive.

TypeScript is JavaScript plus a static type system. "Static" means the checking happens before the program runs — while you type, and again when you build. You describe what a value is allowed to be, and the compiler holds every line to that description.

function applyDiscount(price: number, percent: number): number {
  return price - price * (percent / 100);
}

Now applyDiscount("20", 10) is rejected with a specific complaint: Argument of type 'string' is not assignable to parameter of type 'number'. The error names the wrong value, the expected type, and the exact position. You fix it in seconds instead of hours.

The annotation syntax is a colon after the name: const total: number = 0. You will meet it on variables, parameters, and return types.

Two things worth understanding early, because they explain most of TypeScript's behaviour:

TypeScript erases at runtime. Types are checking instructions for the compiler, not values your program can inspect. The emitted JavaScript has every annotation stripped out. There is no type information left to consult while the program runs, which is why you cannot ask "what type is this variable?" the way you can ask typeof about a value.

A type error does not necessarily stop the build. By default TypeScript still emits JavaScript when it finds type errors, on the theory that you may want to run the parts that are fine while you fix the rest. In this lab you will see both: the error and the output. That is not the lab being lenient — it is the compiler's actual default.

Types are not paperwork you add at the end. They are a description of intent that the compiler enforces for you, forever, on every future edit.

Example

The same calculation with annotations. Note the third call: the compiler objects before this ever runs.

function applyDiscount(price: number, percent: number): number {
  return price - price * (percent / 100);
}

console.log(applyDiscount(200, 10));
console.log(applyDiscount(59.99, 25));

// Uncomment the next line to see the compiler reject it:
// console.log(applyDiscount("200", 10));

Try it yourself

Try it: uncomment the last line and press Run. Read the error, then fix it by passing a number.

Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.

Loading editor…

Guided exercise

Guided exercise

Declare a variable `courseTitle` explicitly typed as `string`, and a variable `lessonCount` explicitly typed as `number`. Give each a sensible value, then log both.

Checks: courseTitle is a non-empty string · lessonCount is a number

Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.

Loading editor…

Stuck? Get a hint.

Independent exercise

Independent exercise

Write a function `secondsToMinutes(seconds: number): number` that converts seconds to whole minutes, rounded down. Annotate both the parameter and the return type. `secondsToMinutes(150)` should return 2.

Checks: secondsToMinutes is defined · secondsToMinutes(150) returns 2 · plus 1 hidden check

Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.

Loading editor…

Stuck? Get a hint.

Common mistakes

  • Believing types still exist at runtime. They are erased during compilation — you cannot check a variable's declared type while the program runs.
  • Annotating everything, including values TypeScript could already infer. The next lesson covers when an annotation adds nothing.
  • Assuming a type error blocks execution. Without `noEmitOnError`, TypeScript still emits JavaScript and the code still runs.

Knowledge check

Knowledge check

1. When does a static type system do its checking?
2. What does the compiled JavaScript output of a TypeScript file contain?
3. Given `function total(a: number, b: number): number`, which call does the compiler reject?

Takeaway

TypeScript checks your intent before the code runs, then erases itself — you get the errors without paying anything at runtime.

Summary

TypeScript adds a static type system to JavaScript. You annotate values with `name: type`, the compiler rejects assignments that contradict those annotations, and the types disappear from the emitted JavaScript.

References

Your notes

Notes save automatically.

Finished this lesson?

Mark it complete to track your progress and schedule a future review.