Bearings
Chapter 01 — Bearings: can you run it and can you read it

You are at the trailhead. Before you walk, you check bearings: does this machine run code, and can your eyes parse what is on the page. Two checks, two minutes, then you read your first real file. The rest of the chapter — the JavaScript you stand on, why a checked layer earns its keep, the compiler, the editor, the repo habit — hangs off those two checks. Pass them and the first lab compiles. Fail one and you know exactly what to fix before the next paragraph.
Do this now (30 seconds, no setup). Open a terminal and run:
node -v # need v18 or newer npx tsc --version
node -vprintsv20.xorv22.x= you can run JavaScript outside the browser.npx tsc --versionprintsVersion 5.x= you can check types. If either printscommand not found, install the current LTS from https://nodejs.org/en/download, reopen the terminal, run both again. No global installs, no ceremony — the project brings its own tools andnpxruns the project’s copy.
Do not skip the second check. Every later drill starts with
npx tsc --noEmit — silence is green, first error is the fix. If
that command is not answering now, nothing after it can teach you.
Aaliyah is on radio at the kiosk, reading the gate mechanism you just
passed to the whole patrol. You will read it with her next — one
if, one string, one gate.
Reading code before writing it: characters, spacing, indent
You have run two commands. Now learn to read the page they will check.
A source file is plain text. Every meaningful character is one of a small set you already know from writing sentences:
- braces
{}, brackets[], parens()group things — open, contents, close. - colon
:labels a value (name: string= name holds text). - comma
,and semicolon;separate items and end statements. - dot
.reaches into a thing (scout.name). - quotes
"'`wrap text; backticks`with${}splice values into text. //starts a comment to end of line;/* */wraps a block. Comments teach, never execute.=assigns;===compares;=>builds a short function;...spreads a copy;?and??guard the missing case (next section).
Spacing and indenting: JavaScript ignores extra spaces, blank lines,
and indent — const x=1 and const x = 1 mean the same. We keep
them anyway because humans read code with eyes. One space after
: and ,, one empty line between ideas, indent two spaces inside
{}. Your editor (Prettier, on save) will fix this for you once
you switch it on below — until then, mimic the register below
character for character.
Read this roster the way Aaliyah does at the trailhead — one record
at a time, name, role, crew, badge number, out loud. Then trace the
function under it that turns a record into a line of text. Amara and
Nizhoni are on Fire crew tonight; the function label builds their
trail tags. If you can point at each : , { } in the block
below and say what it groups, you can read every example that
follows.
The Law on the trail
You just read code out loud. The patrol does the same with the Law: Aaliyah reads five lines and the patrol packs five habits:
- Honest and fair — the compiler reports what is there, not what you hoped was there.
- Considerate and caring — name things so the next reader survives the night.
- Courageous and strong — break the build on purpose in the drills; red is how you learn.
- Use resources wisely — strict mode spends checking now to save debugging later.
- A sister to every scout — every drill answer is verifiable, so no one is left guessing.
The tooling below exists to keep those five. When a rule feels fussy, ask which line of the Law it is keeping.
Our running examples use a trail patrol register: names, roles, crews, badge numbers. The trail is the dataset, never the subject — every example teaches a language fact first. Production examples come second, cut from a shipping codebase (the Sumerian Squares 3D stage), so you see the same shapes in the wild after you have met them at home.
The gate you just passed
You entered through a shared word. Here is the whole mechanism — it is the first production code you will read in this course:
// layouts/partials/courtesy-gate.html (simplified)
if (sessionStorage.getItem(GATE_KEY) === SHARED_WORD) {
showCourse();
} else {
askForWord();
}
One sessionStorage read, one string comparison, one overlay. That
is all. It keeps casual browsers out and nothing more: the word
ships in the page bundle, so anyone who opens DevTools can read it.
Client-side gates are courtesy, not security — server-side auth happens on
a server you control, per request, with secrets the browser never
sees. Remember this shape; Chapter 09 (external data) and Chapter 14
(practices) will show you what the serious version looks like, and
you will know exactly what it is buying you.
Modern JavaScript: the ES2020+ baseline
TypeScript assumes you can read modern JavaScript. You do not need fluency, but the following features appear in every chapter, so meet them here.
const and let declare bindings; const is the default because most
bindings never change. Arrow functions ((s) => s.name) are the short form
you will see in every .map and .filter. Template literals
(`${s.name} holds badge #${s.badge}`) build strings from values.
Destructuring (const { name, role } = scout) pulls fields out of
objects. Spread ([...patrol], { ...scout, badge: 3 }) copies arrays
and objects instead of mutating them.
Optional chaining (scout?.nickname) reads a property only when the value
exists, giving undefined otherwise. Nullish coalescing
(nickname ?? name) falls back only on null or undefined, unlike ||,
which also falls back on "" and 0. These two operators, both from
ES2020, are the JavaScript answer to missing data — TypeScript later makes
the compiler enforce the same care.
Modules tie files together: export shares a binding, import receives
it. A patrol file exports a Scout type and a patrol array; a screen
file imports both. Everything in this course is written as ES modules
(import / export), never the older require style.
export interface Scout {
name: string;
role: string;
crew: string;
badge: number;
}
export const patrol: Scout[] = [
{ name: "Amara", role: "Lookout", crew: "Fire", badge: 3 },
{ name: "Nizhoni", role: "Medic", crew: "Fire", badge: 5 },
];
export function label(s: Scout): string {
return `${s.name} holds badge #${s.badge}`;
}
In the wild: the same shapes run a shipping 3D stage. This
interface from the Sumerian Squares host pool labels every pooled
canvas host — an imported id type, method signatures, one optional
field, and a Map keyed by host:
import type { HostId } from "./types";
export interface PooledHost {
hostId: HostId;
cell: HTMLElement;
canvas: HTMLCanvasElement;
engine: {
dispose(): void;
resize(): void;
runRenderLoop(fn: () => void): void;
stopRenderLoop(): void;
};
regSeq?: number;
}
const pool = new Map<HostId, PooledHost>();
Read it with Chapter 02 eyes: import type borrows only the label
(Chapter 04), regSeq? may be absent (Chapter 08 guards will check),
and the Map holds the same name-to-record shape as the patrol
array above, indexed for lookup. Production TypeScript is this
chapter’s vocabulary at full speed — nothing here is new syntax,
only higher stakes.
JavaScript deserves respect here: it runs everywhere, it improved dramatically with ES2020 and beyond, and every TypeScript program is a JavaScript program underneath. Types add checking; they change nothing about the language’s reach.
New here: modules, interfaces, optional chaining, nullish coalescing. Docs: TypeScript for JavaScript Programmers. Watch: 030 — 100+ JavaScript Concepts (Fireship’s 12-minute checklist — pause on every term you cannot define; each pause is a gap this chapter closes), and for the full prerequisite path, 027 — Learn JavaScript Full Course (freeCodeCamp, Bo Karnes — “from how do you run JavaScript at all through basic syntax, data structures, functions, control flow, and into ES6”).
Why TypeScript
JavaScript fails silently. Subtract a number from a string and you get
NaN, not an error. Read a property off a missing object and you get a
crash at the worst moment — in front of a user. These are not exotic bugs;
they are Tuesday.
A type is a label describing what shape a value has: this binding holds a
string, that function returns a number, this object always carries a
name. The TypeScript compiler checks every label before the code runs.
Whole families of crashes become red squiggles in your editor instead of
blank pages for your users. The check happens at author time, costs nothing
at runtime (types are erased when the code compiles), and documents every
function signature for the next reader.
That is the entire pitch, and the rest of the course is its application: label values, let the compiler verify the labels, and handle the places where outside data arrives without one.
New here: static typing, compile-time checking. Docs:
TypeScript for JavaScript Programmers.
Watch:
079 — TypeScript for Beginners, the Full Hour
(Mosh: “Every JavaScript file is a valid TypeScript file” — and
with the added static typing “we can catch a lot of our mistakes at
compile time” instead of testing every path by hand), then
080 — What TypeScript Is and What to Install
(Shaun’s one-slide version: a superset adding strict types, plus
compile-down of modern features — tsc emits older JavaScript
“which the browsers do understand”). For the motivation reel,
029 — You Don’t Know JavaScript
is twenty-three minutes of the silent failures above, dramatized.
tsc, tsconfig, and project structure
tsc is the TypeScript compiler. Installed per project
(npm install -D typescript), it is run through npx as npx tsc --noEmit
for a pure check — read every file, verify every type, write nothing.
Silence is green; any output is a to-do list, and you read only the first
error, because later errors are usually fallout from the first.
tsconfig.json is the project’s compiler settings file. A Day 1 config is
small and strict:
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"skipLibCheck": true
},
"include": ["src"]
}
target sets the JavaScript version emitted; module and
moduleResolution describe how imports resolve; strict switches on the
full family of safety checks (leave it on — Chapter 02 shows what each one
catches); include scopes the compiler to your source folder.
New here: tsc, tsconfig.json, watch mode. Docs:
TypeScript Tooling in 5 Minutes
plus the tsconfig reference
(one page per option — read the page for every flag in the Day 1
config above). Watch:
081 — Compiling TypeScript
(sandbox file, downlevel emit, --watch) then
085 — Project Workflow with tsconfig
(src, outDir, include — including the stray-root-file trap:
TS6059, fixed with a top-level fence. Also preserved: Shaun
deferring modules with “Um, then we have this one, the module,
using Common JS, we’ll come to that later” — the modules
paragraph in this chapter’s JavaScript baseline collects on that
promise).
Project structure follows one convention through the whole course:
first-project/
package.json
tsconfig.json
src/
hello.ts
hello.test.ts
solution/
hello.ts
src/ holds the code you edit and its tests; solution/ holds a solved
copy you may consult after attempting the lab yourself. node_modules/
holds installed tools and is never committed — .gitignore excludes it
(see the git section below).
Node, npx, and environments
Node.js runs JavaScript (and compiled TypeScript tooling) outside the
browser. This course needs Node 18 or newer; check with node -v. If the
command is missing, install the current LTS from
https://nodejs.org/en/download, reopen the terminal, and verify again.
npm ships with Node and manages the node_modules/ toolbox plus the
scripts in package.json:
{
"scripts": {
"test": "vitest run src/hello.test.ts",
"typecheck": "tsc --noEmit"
}
}
npm test runs the lab suite; npm run typecheck runs the compiler check.
npx runs a binary from the local toolbox without installing it globally —
npx tsc --noEmit uses the project’s own TypeScript version, so every
teammate checks with the same compiler. Never install course tools
globally; the per-project install recorded in package.json is what keeps
npm install reproducible for the next person.
New here: Node as a runtime, npm scripts, npx. Watch:
152 — What Is Node.js
(“Node.js is not a programming language. It is a server-side runtime
environment.” — one language, two runtimes, and everything after is
what that relocation unlocks), then
154 — TypeScript Setup for Node.js
(VS Code, inference, @types) and
155 — TypeScript with Express and Node
(tsc init, scripts, rimraf, concurrently — the script pattern
above, production-flavored). Hands-on: run node -v (need 18+),
then npm run typecheck in the lab kit before writing a line —
silence is your first green.
VS Code: setup for success
VS Code is the course editor, and its TypeScript support is built in — the
same language engine that powers tsc underlines errors as you type.
Four pieces of setup turn it from a text box into a coach.
First, install three extensions: the built-in TypeScript language support (verify it is enabled), ESLint (flags probable mistakes as you type), and Prettier (formats on save so style arguments end forever). Error Lens is strongly recommended: it prints each diagnostic inline, next to the guilty line, so you never have to hover to learn what broke.
Second, switch on format on save, lint on save, and autosave. The loop you want is: type, save (fixes itself, flags the rest), read the inline error, fix, repeat. Every second spent arranging whitespace by hand is a second not spent on types.
Third, use the workspace TypeScript version: open any .ts file, run the
command “TypeScript: Select TypeScript Version”, and pick “Use Workspace
Version”. This binds the editor to the same compiler npm run typecheck
uses, so editor squiggles and terminal output can never disagree.
Fourth, check in the .vscode/ folder. extensions.json recommends the
extensions above to every teammate; settings.json records format-on-save,
the default formatter, and the workspace TypeScript choice; launch.json
stores the debug recipe from the next section. A new clone then behaves
identically on every machine. The first-project lab kit ships a working
.vscode/ — open it, read each file, and copy the pattern into every
project you start.
VS Code debugging: launch configs, breakpoints, sourcemaps
When reading an error is not enough, run the code under the debugger.
A launch configuration in .vscode/launch.json tells VS Code how:
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Debug current test",
"program": "${workspaceFolder}/node_modules/vitest/vitest.mjs",
"args": ["run", "${file}"],
"console": "integratedTerminal"
}
]
}
Set a breakpoint by clicking left of a line number in any .ts file —
execution pauses there and you can inspect every binding. Sourcemaps are
the quiet machinery that makes this work: the debugger runs compiled
JavaScript but shows you the TypeScript you wrote, mapping each running
line back to its source. Vitest and tsx-style runners handle this
mapping for you; if you ever compile with tsc yourself and want to debug
the output, enable "sourceMap": true in tsconfig.json so the .js.map
files exist. Debug the test, hover the value, find the wrong shape, fix
the type — that loop resolves more confusion than any amount of staring.
New here: launch configs, breakpoints, sourcemaps. Watch
079 — TypeScript for Beginners, the Full Hour
again, Part A only — its debugging walkthrough is the visual
companion to the config above. Hands-on: set one breakpoint in the
lab’s hello.test.ts, run the “Debug current test” config, and
hover a binding before reading further.
Git basics: the clean-repo habit
Git records what changed, when, and why. The daily vocabulary is small:
clone copies a repository to your machine; add stages files for the
next snapshot; commit takes the snapshot with a message describing it;
branch starts a named line of work; diff shows unstaged changes before
you commit them.
.gitignore lists files Git must never track. Every course project ignores
at least node_modules/ (rebuilt by npm install), editor swap data, and
compiled output:
node_modules/
dist/
*.local
The clean-repo habit: before every commit, run git status, read what is
staged, and confirm nothing generated or private slipped in. A repository
where git status is quiet and every file is either source or declared
configuration is a repository a stranger — or you, in six months — can
clone and run with two commands. The first-project kit ships the
.gitignore above; keep it.
DIY simulator drills
No tooling needed — you are the simulator. Cover the answers, run each drill in your head or on paper, then verify with the tool itself. Wrong predictions are the lesson; log each miss in one sentence.
Be the compiler. Under
strict: true, which lines error, and with what complaint?let nickname: string; nickname = "Zola"; const crew: string = 5; const label = `crew ${crew.toUpperCase()}`;Verify: paste into any
.tsfile, runnpx tsc --noEmit, read only the first error. (Drills the “read the first error” habit — later errors are fallout.)Be the runtime. No types, just JavaScript — what prints?
console.log("badge " + 3 - 1); console.log(0 ?? "Fire crew"); console.log(0 || "Fire crew");Verify with
node -e. This is the silent-failure family the “Why TypeScript” section promised; feel each one before the compiler takes them away in Chapter 02.Be the watcher. A project has
src/sources androotDir: "./src"/outDir: "./public"set, but noincludeyet; a straynotes.tssits at the root. You runnpx tsc --watch. Does the watcher stay quiet? (Answer: no — the trap from video 085:error TS6059, the stray file is not underrootDir, “and the watcher says so loudly”. The fix is a top-level fence,"include": ["src"], not another compiler option. Reproduce it in the lab kit with an actual stray file, read the TS6059, fence it, delete the stray.)Be the debugger.
greet(" ")throws per its contract, and the stack points at thethrowline, not the caller. Without running anything, write down the two clicks that land you on the guilty caller frame (hint: the section above names both). Verify in VS Code with the lab config.
Lab: set up and compile your first project
Download the first-project kit, run its setup script, and watch the
suite go red — red first, always. Open src/hello.ts (its header
comment carries the full procedure), implement the two functions, and
drive the suite green with npm test, then confirm zero type errors
with npm run typecheck. Break one function once on purpose, watch
exactly one test go red, then restore green. The habit — red, green,
deliberate red, green — is the deliverable of Day 1.
Resources
Docs, in the order the chapter introduces them:
- TypeScript for JavaScript Programmers (baseline, why-types)
- TypeScript Tooling in 5 Minutes (tsc, config)
- tsconfig reference (every Day 1 flag)
- The Basics (handoff to Chapter 02)
- Everyday Types (handoff to Chapter 02)
- Object Types (Scout and PooledHost, formalized)
Videos — the chapter’s shelf, section-mapped (quoted lines are the instructor’s own words as preserved in each companion entry):
- Baseline: 030 — 100+ JavaScript Concepts · 027 — Learn JavaScript Full Course · 101 — THINK in Code: Hard Parts · 102 — Modern JavaScript Full Beginner Course · 157 — How to Learn JavaScript Fast
- Why types: 079 — TypeScript for Beginners, the Full Hour (“Every JavaScript file is a valid TypeScript file”; “we can catch a lot of our mistakes at compile time”) · 080 — What TypeScript Is and What to Install (“which the browsers do understand”) · 022 — What is TypeScript / Install / vs JavaScript · 023 — Learn TypeScript Full Course · 029 — You Don’t Know JavaScript · 032 — Datatypes in TypeScript
- Toolchain: 081 — Compiling TypeScript · 085 — Project Workflow with tsconfig (“Um, then we have this one, the module, using Common JS, we’ll come to that later”) · 001 — TypeScript Tutorial for Beginners · 002 — Introduction and Setup · 003 — Compiling TypeScript · 004 — Type Basics · 005 — Objects and Arrays · 006 — Explicit Types · 007 — Project Structure with tsconfig · 082 — Type Basics, Inference · 083 — Objects and Arrays, Shapes · 084 — Explicit Types, Annotations
- Runtime: 152 — What Is Node.js (“Node.js is not a programming language. It is a server-side runtime environment.”) · 153 — Node.js, The Documentary · 154 — TypeScript Setup for Node.js · 155 — TypeScript with Express and Node · 156 — Event Loop, Visualized
Hands-on: drill set above (paper first, tools second), then the
first-project lab kit — red, green, deliberate red, green.