084 — Explicit Types (declare now, assign later: annotations, arrays, unions, objects)
Full companion narrative for TypeScript Tutorial #5 — explicit annotations for deferred values, typed arrays with the empty-array init rule, union types with the parentheses-before-brackets rule, and shaped object types
Video: 084 · TypeScript Tutorial #5 - Explicit Types · watch · ~8:35 · Net Ninja TypeScript tutorial series, lesson 5 (Shaun)
Source: this is a written companion to the video. Part of the Favorite TypeScript Videos curated path, module 00 (foundations). Inference needs a value to read from — this lesson covers what to do when the value comes later.
annotate up front when the value comes later
let character: string;
let age: number;
let isLoggedIn: boolean;
character = "luigi"; // fine
age = 30; // fine
isLoggedIn = true; // fine

Lessons 3–4 inferred every type from an initializer. Here there is nothing to infer from yet, so the annotation carries the contract: “if I try to give it a value of a string, like Luigi, it’s not gonna let me do this, and we get an error.”

The commented-out counterexamples stay in the file as documentation: age = 'luigi' and isLoggedIn = 25 would each fail the declared type.

typed arrays — and the empty-array init rule
let ninjas: string[] = ["shaun", "ryu", "chun-li"];
ninjas.push("ken"); // fine

The element type goes before the brackets. Then the gotcha that earns its own browser trip: declaring let ninjas: string[] without initializing compiles cleanly, but the first push throws at runtime — “we get an error here. It says cannot read property push of undefined.” The fix is to initialize to [] whenever you plan to push.

union types widen what is allowed
let mixed: (string | number | boolean)[] = [];
mixed.push("hello"); // fine
mixed.push(20); // fine
mixed.push(false); // fine — console shows (3) ["hello", 20, false]

Parentheses before the brackets are required — (string | number | boolean)[]. “So I could come down here and say mixed.push, and it’s gonna be a string. hello, that would be fine.”
The same | works for scalars: let uid: string | number takes '123' or 123, but not false.

objects: from loose to shaped
let ninjaOne: { name: string; age: number } = { name: "yoshi", age: 30 };
let ninjaTwo: { name: string; age: number; beltColour: string };

A bare : object annotation is loose — it still admits arrays — while a shaped literal enforces required properties and rejects excess ones. “We’re just declaring the type it should be in the future.” First taste of structural typing; lesson 9 (type) and lesson 10 (signatures) build directly on it.

Prev: 083 — Objects and Arrays · Next: 085 — Project Workflow with tsconfig
The auto-transcript mishears a few terms; this narrative uses the corrected forms: declaring a variable without initializing it (transcript “initializing a variable without giving it a value”), annotating the variable with a type (transcript “giving the variable a type”), initializing the array as an empty array, and union type for multi-type positions (transcript “one of two or one of three types”).