Topic 1.1
Type Annotations
In one line
A type annotation is a colon and a type written after a name (age: number). It is a promise the checker holds you to on every line that uses the name.
Think of it like this
A label on a storage box. A box labelled "batteries" tells everyone what belongs inside, and if someone drops a banana in, you notice the mistake straight away. An annotation is that label. You write : number after a name, and from then on the checker looks at every place that name is used and complains when a banana shows up.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- Annotation
- The
: typeyou write after a name to say what kind of value it holds. - Parameter
- A name in a function's brackets that receives a value when the function is called.
- Argument
- The actual value you pass for a parameter when you call the function.
- Return type
- The type of the value a function hands back, written after the closing bracket as
: type. - Assign
- To store a value in a name with
=. The value must fit the name's type. - Assignable
- A value is assignable to a type when it fits there. The message "Type 'string' is not assignable to type 'number'" means a string can't be stored where a number is promised.
- Compile time
- The moment the checker reads your code, before it runs. Annotation errors appear here.
- Erased
- Removed. Annotations are deleted when the code becomes JavaScript, so they never exist at runtime.
- TS code
- The number after
TSin an error (likeTS2322). It names the kind of error and never changes.
Step by step
01Name, colon, type
Start with the smallest piece. After the variable's name, add a colon and the type.
string is text, number is any number (whole or decimal) and boolean is true or false. These three are written in lower case.
let city: string = "Pune";
const year: number = 2026;
let done: boolean = false;02Annotate a function: parameters and result
Each parameter gets its own annotation. The return type goes after the closing bracket.
Now the signature (the first line) says everything a caller needs: area takes two numbers and gives a number. Hover over the name in your editor and you see exactly that line.
function area(width: number, height: number): number {
return width * height;
}
const double = (n: number): number => n * 2;03What the checker does with a promise
Whenever a value flows into an annotated name, the checker asks one question: does this value fit the type?
Assigning "ten" to score: number fails with TS2322 (Type 'string' is not assignable to type 'number'). Returning a number from a function that promised a string fails the same way, on the return line.
04Where errors point
An error line looks like index.ts(5,3): error TS2322: .... Read it as: file index.ts, line 5, column 3, error code TS2322, then the message.
The position is where the broken promise happens: for a wrong return value it is the return itself. You will use this to find the real cause quickly.
05Annotations are erased
When TypeScript writes the JavaScript, every annotation is cut out. Nothing about it remains for the browser.
That is also why code with a type error still runs in the live examples: the checker complains, the JavaScript that is left does its best, and the console shows what actually happened.
function area(width, height) {
return width * height;
}
const double = (n) => n * 2;Try it yourself
- 1
Fix the return
In the second example, change
: stringonlabelto: number. Predict what happens to the second error before you look.It disappears, because now the promise matches the value. Either side can be the wrong one: first decide whether the promise or the value is what you meant.
- 2
Call it wrongly
In the first example add the line
area("3", 4);. Which column does the error point at, and what does the message say the expected type was? - 3
Delete a promise
Remove
: numberfrom thedoublearrow function's parameter, so it reads(n): number => n * 2. A new kind of error appears; the message ends with "implicitly has an 'any' type". That is the rule from the walkthrough: parameters need your help.
Code & diagrams
Hover answers appear in the Types panel. Notice that year is shown as number: you annotated it, so TypeScript uses your type. Without the annotation it would be the exact value 2026 (Topic 1.3).
Console
(nothing was printed)Expected console output
Pune 2026 false
12 42Both errors are TS2322. The first points at the assignment, the second at the return statement. The JavaScript still runs and prints the wrong kinds of values: a string where a number was promised, and a number where text was promised.
Console
(nothing was printed)Expected console output
ten 8Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Return the wrong kind of value
In the second example, label promises string but returns n * 2, a number.
Myth vs fact
Myth
Annotations change how the program runs.
Fact
They are deleted before the code runs. The same JavaScript would result without them; annotations only change what the checker allows.
Myth
You must annotate every variable.
Fact
Most variables are inferred correctly from their first value. Annotate parameters, and add others only when they help the reader or fix a wrong guess (Topic 1.3).
Myth
An annotation checks the value while the program runs.
Fact
It is checked once, by reading the code. At runtime nothing verifies that a number really is one; if bad data sneaks in (Topic 13.4), the annotation can't notice.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
The checker asks one question at every annotated position: is the source type assignable to the target type? Almost every error you will ever see is that question answered "no". The code
TS2322is the general form (assignment and return),TS2345is the same question for a function argument. - ▸
Because the annotation is erased, TypeScript can't use it to optimise anything. JavaScript engines don't see your types. Speed comes from the way you write the JavaScript, not from the types.
- ▸
Return annotations are also a performance and stability tool: on a public function an explicit return type stops a change deep inside the body from silently changing what callers see, and it lets the compiler skip re-deriving the type. Libraries enforce this with
isolatedDeclarations(Topic 11.3).
Remember this
- 1
The problem this solves: plain JavaScript happily lets a piece of text flow into a place that expects a number, and the mistake only shows up later, in front of a user. An annotation states what a name is supposed to hold, so the checker can stop the mistake before the program runs.
- 2
The syntax is always the same: name, colon, type.
let city: string = "Pune";reads "cityis a string, and it starts as Pune". The colon part is the type annotation. It exists only for the checker: when the program is turned into JavaScript the annotation is simply deleted, so it costs nothing at runtime (Topic 0.2). - 3
Annotations go in three main places. On a variable:
let done: boolean = false;. On a parameter (a name a function receives):function area(width: number, height: number). And after the closing bracket of a function, for its return value:function area(...): number { ... }. Arrow functions work the same way:const double = (n: number): number => n * 2;. - 4
An annotation is a promise in two directions. Every value put into the name must fit the type (
score = "ten"breaks the promise ofscore: number), and every use of the name may rely on the type (anumberalways has.toFixed(), but never.toUpperCase()). A return annotation promises the same for the function's result: if anyreturnhands back the wrong kind of value, the error is reported on thatreturnline, not on the caller, so you find the bug where it was made. - 5
A parameter annotation is the one you must usually write yourself. A function can be called from many places, so TypeScript can't work out what it will receive. With no annotation the parameter would be
any("anything goes"), and strict mode, which is on by default in new projects, refuses and reportsTS7006(Topic 0.1, Topic 1.6). That one rule is why you will write far more parameter annotations than any other kind. - 6
Types are written after the name, not before as in Java or C (
int age). The reason is practical: in JavaScript a declaration begins withlet,constorfunction, and TypeScript only adds an optional ending. Because of that, deleting every annotation always leaves valid JavaScript. - 7
You don't have to annotate everything. When you write
let city: string = "Pune", the: stringrepeats what TypeScript already knows from the value. Topic 1.3 explains inference and a clear rule for when an annotation helps and when it is noise. For now: annotate parameters, usually annotate return values of exported functions, and let simple variables be inferred.
Explain it without notes
What is a type annotation and where can you write one?
Why do function parameters usually need annotations while many variables don't?
Are annotations present at runtime? What follows from the answer?
A function promises : string but one branch returns a number. Where does TypeScript report the error, and why there?
Practice
Write a function fullName that takes first and last (both text) and returns the two joined with a space. Annotate every parameter and the return value. Then call it with a number and write down the error.
This arrow function has no annotations. Add them so it takes a number of items and a price per item (both numbers) and returns the total as a number.
``ts
const total = (count, price) => count * price;
Trade-offs
- ↔
More annotations make code self-explaining and catch changes early, but repeat what the compiler already knows and add noise. A good balance: annotate function boundaries, trust inference inside.
- ↔
A return annotation can be wider than the real result (you declare
: string | nulland always return text), which hides precision from callers. Annotate what you want to promise, not what you happen to return today.
Done when you can
I can write the name, colon, type form on a variable, a parameter and a return value.
I can say what a type annotation promises and in which two directions.
I can read
index.ts(5,3): error TS2322: ...and find the line and column.I can explain why annotations are free at runtime.
I can explain why parameters need annotations in strict mode.