Lab 01: Hello World & Basics
Objective
Set up TypeScript, compile .ts files to JavaScript, understand the TypeScript compiler (tsc), and write your first typed program.
Background
TypeScript is a statically typed superset of JavaScript created by Microsoft. Every valid JavaScript file is valid TypeScript — TypeScript adds optional type annotations that are erased at compile time. The result is plain JavaScript that runs anywhere JS runs. TypeScript's killer feature: it catches bugs at compile time that JavaScript would only reveal at runtime.
Time
20 minutes
Prerequisites
Basic JavaScript knowledge
Tools
Docker image:
zchencow/innozverse-ts:latest(Node 20 + TypeScript 5.x)Run:
docker run --rm -it zchencow/innozverse-ts:latest
Lab Instructions
Step 1: Your First TypeScript File
Run with ts-node:
💡 TypeScript type annotations are written as
: TypeNameafter a variable or parameter. They're completely erased when compiled to JavaScript — zero runtime overhead. The TypeScript compiler (tsc) checks types statically before any code runs.
📸 Verified Output:
Step 2: Primitive Types
💡
unknownis safer thanany— withany, TypeScript trusts you completely (no checking). Withunknown, TypeScript requires you to narrow the type before using it. Useunknownfor values from external sources (JSON, user input, API responses) and narrow withtypeof,instanceof, or type guards.
📸 Verified Output:
Step 3: Arrays & Tuples
💡 Tuples encode position-dependent meaning.
[number, number]for a point is cleaner than{x: number, y: number}for math operations, and cleaner than justnumber[](which could be any length). React'suseStatereturns a tuple:[state, setState]— that's why you destructure it.
📸 Verified Output:
Step 4: Object Types & Interfaces
💡
interfacevstype: Both define shapes. Useinterfacefor object shapes (it's extendable withextends). Usetypefor unions, intersections, and complex types. A key difference:interfacecan be "declaration merged" — twointerface Userdeclarations merge into one.typecannot be reopened.
📸 Verified Output:
Step 5: Type Aliases
💡 String literal unions (
"active" | "inactive") are one of TypeScript's most useful features. They're like enums but lighter — you get autocomplete, type checking, and exhaustiveness checking inswitchstatements. Use them for status fields, directions, HTTP methods, and any closed set of string values.
📸 Verified Output:
Step 6: tsconfig.json Overview
💡
strict: trueenables 8+ strict checks with one flag. The most important:strictNullChecksmakesnullandundefinedtheir own types — astringvariable can't benullunless you writestring | null. This eliminates entire classes of "Cannot read property of null" runtime errors.
📸 Verified Output:
Step 7: Compiling TypeScript
💡
ts-nodecompiles and runs TypeScript in one step — perfect for learning and scripting. For production, compile withtscfirst (produces.jsfiles), then run withnode.ts-nodeis slower (compiles on every run) but eliminates the build step during development.
📸 Verified Output:
Step 8: Complete — Type-Safe Calculator
💡
Record<K, V>is a built-in utility type that creates an object type with keys of typeKand values of typeV.Record<Operation, string>means "an object where every Operation key must be present with a string value." This gives exhaustiveness checking — if you add a new Operation, TypeScript errors until you add it to the Record.
📸 Verified Output:
Verification
Summary
TypeScript adds a powerful type system on top of JavaScript. You've covered primitive types, inference, arrays, tuples, interfaces, type aliases, literal unions, strict mode, and a complete type-safe calculator. The type annotations disappear at runtime — you get the benefits of static typing with zero runtime cost.
Further Reading
Last updated
