079 — TypeScript for Beginners, the Full Hour (setup, tsc, tsconfig, and the type system)
Full companion narrative for the Mosh TypeScript beginners course: static typing, toolchain setup, tsconfig tour, VS Code debugging, any/unknown/never, arrays, tuples, enums, functions, objects, aliases, unions, narrowing, and null handling
Video: 079 · TypeScript Tutorial for Beginners · watch · ~64:27 · Programming with Mosh (Mosh Hamedani)
Source: this is a written companion to the video. Part of the Favorite TypeScript Videos curated path, spanning module 00 (foundations: setup, compile, tsconfig, debugging) and module 01 (fundamentals: the type system). Mosh frames the hour as three questions — what is TypeScript, why do we need it, how is it different — then answers by building.
1. what, why, how is it different
TypeScript is JavaScript with compile-time type checking. “Every JavaScript file is a valid TypeScript file,” but the added static typing means “we can catch a lot of our mistakes at compile time” instead of running the app and testing every path.

let age: number = 20;
age = "a"; // compiler stops us here — no need to run the app to find it
Catching happens at compile time — no need to run the app or exhaustively unit-test every path. Headline benefits beyond the types: editor completion and refactoring ride on the same type info, and future-JavaScript features compile down to compatible output. Drawbacks stated up front: a compilation step (browsers do not run .ts), and more discipline than quick scripts need.

2. toolchain: install, first program, tsconfig, debug
Four moves: npm i -g typescript (with the sudo note for Mac/Linux permission errors), tsc --init to scaffold tsconfig.json, bare tsc to build per config, and a VS Code launch.json (“launch program,” F5) with breakpoints, step-over, and watched variables.

First program: new folder, index.ts with console.log('hello-world'), compile with tsc index.ts (emits index.js). Annotate (let age: number = 20) and the bad assignment errors at compile time; default emit targets ES5 (let becomes var) and annotations never reach the output.

tsconfig highlights: target/lib (which JavaScript the emit may use), module, outDir/rootDir, removeComments, sourceMap, and the strict main switch enabling the core check family.

Debugging: enable sourceMap, create launch.json, set a breakpoint, F5, step with F10 while watching variables.

3. any opts out — noImplicitAny keeps you honest
Unannotated dynamic values infer any, which silently disables checking. Mosh’s rule is blunt: disabling noImplicitAny means “there’s really no point using TypeScript because you will lose the major benefit of TypeScript.”
Companions: unknown (narrow before use), never (unreachable), and the hygiene flags noUnusedLocals/noUnusedParameters (“X is declared, but its value is never read” — delete it) and noImplicitReturns for uncovered branches. The strictness flags stay on — never disabled.
4. arrays, tuples, enums
Arrays narrow element types (number[] rejects '3') and unlock IntelliSense:
let numbers = [1, 2, "3"]; // element types inferred — pushes must match

Tuples fix length and per-position types ([number, string] pairs) but can leak on push since they compile to plain arrays:
let user: [number, string] = [1, "Mosh"];
![tuple declaration: let user: [number, string]](/_assets/favorite-typescript-videos/079-mosh-typescript-beginners/frame-0032.png)
Enums list related constants (enum Size { Small, Medium, Large }) — prefer const enum for optimized emit.

5. functions and objects carry contracts
function calculateTax(income: number, taxYear = 2022): number { ... } // default + inferred return
type Employee = { readonly id: number; name: string; retire?: (d: Date) => void };
let weight: number | string; // union
type Qty = 50 | 100; // literal

Functions always annotate params and return type; the compiler enforces arity, with optional (taxYear?: number) and default (= 2022) parameters. Objects take inline shape annotations with readonly and ? modifiers, but repeated shapes move to a type alias (PascalCase). Unions (number | string) widen — “With union types, we can give a variable or a function parameter more than one type” — intersections (Draggable & Resizable) combine, and literals (50 | 100, 'cm' | 'inch') limit values: “Sometimes we want to limit the values we can assign to a variable. This is where we use literal types.”
The kgToLbs demo pairs a union parameter with typeof narrowing to split the branches before type-specific use:

6. null handling: guards to operators
customer?.birthday?.getFullYear(); // optional chaining replaces the null/undefined if
speed ?? 30; // nullish coalescing: default only for null/undefined
customers?.[0]; // optional element access for possibly-empty arrays

The explicit if (customer !== null && customer !== undefined) guard works, but the optional-chaining operator ?. replaces it — with ?? and ?.[] covering defaults and array access — all under strictNullChecks, which turns accidental null/undefined into a compile error instead of a runtime crash.
Transcript notes: The auto-transcript mishears a few terms; this narrative uses the corrected
forms: sudo prefix (not “pseudo”) for global npm installs on Mac/Linux permission errors, tsc --init (not “double hyphen in it”) for scaffolding tsconfig.json, the strict umbrella flag
(not “type checking section”) enabling the core check family, “catch these errors” (not “cache”)
for compile-time catching, and the Resizeable demo type intersected with Draggable for the
UIWidget intersection example. The outro promo (cheat sheets, money-back guarantee, completion
certificate) is a paid-course upsell, not course content.
Prev: 078 — Multi-Step Form with a Reusable useMultistepForm Hook · Next: 080 — What TypeScript Is and What to Install