Without notes, state yesterday’s main idea and one unresolved question.
TypeScript basic types
TypeScript, Packages, and Tooling
Objective
Annotate domain data and catch obvious mismatches.
TypeScript is similar to design-rule checking: it catches invalid connections before runtime but cannot prove system behavior.
- primitive types
- arrays and object types
- function parameter and return types
Why this matters
On Day 15 you learned that most beginner bugs are not logic errors — they are a value quietly
being the wrong type, the text "42" where the number 42 was meant. JavaScript only finds out
when the code runs, and often not even then. Today you start writing TypeScript, which finds
that class of mistake before the program runs at all. By the end of the hour your inventory model
and calculator functions will be typed, and you will have deliberately broken and fixed three type
errors so you can recognise them at speed.
What TypeScript is, and what it is not
TypeScript is JavaScript plus type annotations — small notes saying what kind of value each
name is allowed to hold. A program called the compiler (tsc) reads those notes, checks that
every use is consistent, and reports mismatches. Then the annotations are erased: what runs in
the browser is ordinary JavaScript with the types stripped out.
That leads to the two facts that matter most this week, and they must be held together.
What it does: it checks types before the code runs. That is called static checking — static because nothing is executing. It catches mismatched shapes, misspelled property names, wrong argument types, and missing fields.
What it does not do: it cannot prove your program is correct. It has no opinion about whether
your total is calculated correctly, whether you meant < or <=, or whether the JSON that arrives
at runtime really has the shape you claimed. TypeScript checks consistency with what you declared.
If you declare something false, it will happily check your false statement.
TypeScript is design-rule checking
Before a board is fabricated, DRC runs over the layout and reports invalid connections: a trace narrower than the spec, two nets shorted, a footprint whose pad count does not match the part. That is enormously valuable and it is cheap, because it happens before any copper is etched. What DRC will never tell you is whether the circuit does the job — a DRC-clean board can be a perfectly manufacturable amplifier that oscillates. TypeScript is DRC for your code: invalid connections caught before runtime, and no claim at all about behaviour.
Primitive types
A type annotation is a colon and a type name after the variable name.
const componentName: string = "Resistor 10k";
const resistanceOhms: number = 10000;
const inStock: boolean = true;
The three primitives you will use constantly are string, number, and boolean — the same three
you met on Day 15, now written down. They are lowercase; String with a capital S is a different
thing and almost never what you want.
Most of the time you should not write the annotation. TypeScript performs inference: it works out the type from the value you assigned.
const componentName = "Resistor 10k"; // inferred as string
let stockCount = 42; // inferred as number
stockCount = "forty two"; // error
error TS2322: Type 'string' is not assignable to type 'number'.
Read that error as a sentence: you tried to put a string where a number was expected. TS2322
is the error's catalogue number, and searching it finds thousands of explanations. Annotate when
inference cannot see your intent — function parameters, empty arrays, outside data — and let
inference do the rest.
Arrays and object types
An array of numbers is number[] — the element type followed by square brackets.
const stockLevels: number[] = [42, 7, 0];
const names: string[] = ["Resistor 10k", "Capacitor 100n"];
For the shape of an object, give it a name with a type alias: the keyword type, a name, and
a description of each property.
export type Component = {
id: string;
name: string;
category: string;
stock: number;
unitPriceCents: number;
};
Type aliases are conventionally capitalised. Now Component[] means "an array of those". If an
object is missing a required property, you hear about it immediately:
const capacitor: Component = {
id: "c-100n",
name: "Capacitor 100n",
category: "passive",
stock: 90,
};
error TS2741: Property 'unitPriceCents' is missing in type
'{ id: string; name: string; category: string; stock: number; }'
but required in type 'Component'.
In plain JavaScript that object is accepted silently, and you discover the missing field three
screens later when a price renders as undefined.
The form with required boxes
A paper form with required fields is checked at the counter, before it joins the queue. A form with no required fields is accepted by the counter and rejected two weeks later by someone who needed the missing box. The type alias is the list of required boxes.
Function parameter and return types
Functions are where types pay for themselves, because a function is a contract between two pieces of code. Annotate each parameter, and the return type after the parameter list.
export function totalValueCents(items: Component[]): number {
let total = 0;
for (const item of items) {
total = total + item.stock * item.unitPriceCents;
}
return total;
}
export function isLowStock(item: Component, threshold: number): boolean {
return item.stock < threshold;
}
Two separate protections come from this. Callers are checked:
isLowStock(resistor, "5");
error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
And the body is checked against its own promise — a : boolean function that returns a string is
an error, so the annotation is not a comment that can drift out of date.
Parameter annotations are effectively required. Leave one off and the compiler objects:
error TS7006: Parameter 'x' implicitly has an 'any' type.
any is the escape hatch: a type meaning "stop checking this value". It is occasionally
necessary and almost always a mistake in your own code, because one any silently switches
checking off for everything downstream of it. Today's deliverable requires zero uses of it.
Thirty seconds
In any .ts file, write const n: number = 5; then on the next line n.toUpperCase();. Save
and run npx tsc --noEmit. TypeScript knows numbers have no toUpperCase — an error you would
otherwise have met at runtime, in front of a user.
Walkthrough
Work in the Vite project you scaffolded yesterday.
cd ~/fullstack-journey/inventory-ts
First confirm strict checking is on, because everything above depends on it. Open tsconfig.json
and look for "strict": true. Recent TypeScript versions enable strict checking by default, so it
may be absent — test rather than assume. Create src/inventory.ts:
export type Component = {
id: string;
name: string;
category: string;
stock: number;
unitPriceCents: number;
};
export function totalValueCents(items: Component[]): number {
let total = 0;
for (const item of items) {
total = total + item.stock * item.unitPriceCents;
}
return total;
}
Add a temporary line const bad: number = null; and run the type check:
npx tsc --noEmit
src/inventory.ts(13,7): error TS2322: Type 'null' is not assignable to type 'number'.
Real tsc output leads with the file and the (line,column) of the fault, so your numbers will
differ from these. If instead it reports nothing, strict checking is off — add "strict": true inside
compilerOptions in tsconfig.json and run again. Delete the temporary line. Now add a value and
a caller that are both wrong on purpose:
const resistor: Component = {
id: "r-10k",
name: "Resistor 10k",
category: "passive",
stock: "42",
unitPriceCents: 3,
};
console.log(totalValueCents(resistor));
src/inventory.ts(17,3): error TS2322: Type 'string' is not assignable to type 'number'.
src/inventory.ts(21,29): error TS2345: Argument of type 'Component' is not assignable to parameter of type 'Component[]'.
Type 'Component' is missing the following properties from type 'Component[]': length, pop, push, concat, and 35 more.
Two real bugs, neither of which would have appeared until the code ran. Fix them — stock: 42, and
pass [resistor] — and confirm npx tsc --noEmit prints nothing at all. Silence is success,
the convention you first met on Day 2.
Checkpoint
Explain the second error in plain JavaScript terms: you handed the function one object where it expected a list of objects, so the loop would have iterated over nothing.
How to use AI today
Today's mode is tutor. The best tutor-style request asks the AI to explain the concept, give a small example, and then let you attempt it — never to hand you a corrected file. With type errors there is a specific version of that request worth memorising.
Tutor mode, on your first real error
"Explain each TypeScript error in plain JavaScript terms before showing a correction." Read the explanation, close it, and write the fix yourself. If you paste in a fix you cannot narrate, you have swapped a five-minute lesson for a permanent gap.
Your turn
- In
src/inventory.ts, define theComponenttype alias with at least the five properties above. Addidas astring, not a number — you will thank yourself in Week 7. - Write
totalValueCents(items: Component[]): numberandisLowStock(item: Component, threshold: number): boolean, ported from your Week 4 calculator logic. - Add a third annotated function of your own, such as
formatPrice(cents: number): string. - Create a
Component[]array of three real components and call all three functions fromsrc/main.ts. Runnpm run devand confirm the values print in the browser console. - Now break it three times, one at a time, running
npx tsc --noEmitafter each and writing the full error text intonotes/day-31.md:- put a string in a
numberproperty (expect TS2322), - remove a required property from one component (expect TS2741),
- pass an argument of the wrong type to one of your functions (expect TS2345).
- put a string in a
- Fix all three. Confirm
npx tsc --noEmitprints nothing, then runnpm run buildand confirm it completes. - Search your files for the word
any. There should be none. Commit.
You are done when
npx tsc --noEmit is silent, npm run build succeeds, and notes/day-31.md holds three real
error messages with a one-line plain-English translation of each.
Common pitfalls
- Reaching for
anyto make an error go away. The error was information.anydeletes the information and keeps the bug. - Believing a clean type check means the code works. It means the shapes agree. Your maths can still be wrong, and you still have to run it.
- Renaming
.jsto.tsand panicking at fifty errors. That is normal and it is a to-do list. Convert one file at a time and start with the data model. error TS6133: 'x' is declared but its value is never read. Not a type mismatch — the project is configured to flag unused variables. Delete it or use it.
Verify it yourself
Open today's reference, the TypeScript Handbook, and read The Basics and Everyday Types.
- The Handbook states what happens to type annotations when the code is compiled. Copy that sentence into your notes. Does it match this lesson's claim that types are erased?
- Everyday Types shows a second syntax for array types besides
number[]. Find it and note it. - Find the Handbook's own warning about
any, and write down its reason in your words.
Confirming a lesson from the official docs is the point of this section — do it before you close the tab.
The hour
- 0–5 min Recall
- 5–20 min Learn
Read only the listed concept notes and official reference sections needed today.
- 20–48 min Build
Type the component inventory model and calculator functions. Deliberately create and fix three type errors.
- 48–55 min Explain and verify
Run the result, inspect evidence, and explain the data/control flow in your own words.
- 55–60 min Quiz and commit
Complete the quiz, record one lesson, and commit the verified change when applicable.
What to hand in
Typed models with no use of any.
Working with AI today
Ask for explanations, analogies, questions, and hints. Do not request a complete finished solution first.
Explain each TypeScript error in plain JavaScript terms before showing a correction.
References
End-of-day quiz
Explain-back gate
Pass the quiz above to unlock completion.
Quiz + explain-back checks required.