083 — Objects and Arrays (element types, union seeds, frozen shapes)
Full companion narrative for TypeScript Tutorial #4 — homogeneous arrays locking element types, mixed arrays as inferred unions, and objects freezing shape: no new props, no missing props, no type swaps
Video: 083 · TypeScript Tutorial #4 - Objects & Arrays · watch · ~7:35 · Net Ninja TypeScript tutorial series, lesson 4 (Shaun)
Source: this is a written companion to the video. Part of the Favorite TypeScript Videos curated path, module 00 (foundations). Arrays and objects inherit the lesson-3 rule — the type you start with is the type you’re stuck with — applied to collections.
homogeneous arrays lock their element type at birth
let names = ["luigi", "mario", "yoshi"];
names.push("toad"); // fine
names.push(3); // error: Argument of type 'number' is not assignable to parameter of type 'string'
names[0] = true; // error — index assignment checked too

“When we declare a new array, the types that we assign into that array cannot then be changed later on” — push, index write, and even reassigning the variable itself away from array type all fail.

Hovering the push shows the assignability error — a number against a string-element array — because the seed fixed the element type at declaration.


mixed arrays are unions inferred from the seed
let mixed = ["chun-li", 4, "ryu", 8, 9]; // (string | number)[]
mixed.push("ryu"); // fine mixed.push(8); // fine
mixed[0] = 3; // fine — position types are fluid within the union
Declare the variety up front and TypeScript “will look at this and say, OK, well this is an array now, which can contain strings or numbers” — after that, positions freely swap between the member types.

objects freeze shape: no new props, no missing props, no type swaps
let ninja = { name: "mario", belt: "black", age: 30 };
ninja.age = 40; // fine — number to number
ninja.age = "30"; // error — type change refused
ninja.skills = []; // error — skills never existed on ninja
ninja = { name: "yoshi", belt: "orange", age: 40 }; // fine — whole object, same structure
ninja = { name: "yoshi", belt: "orange" }; // error — age missing

Properties “work the same way as variables,” but the object adds a structural contract: replacement values must carry exactly the initial property set at the initial types. The rejected skills add-on (ninja.skills = ["fighting", "sneaking"]) is the canonical example of the no-new-props rule, and whole-object reassignment (“override the whole thing”) is allowed only with identical structure.

“it doesn’t match the initial structure of this object that we initially declared. Once we initially declare something like this, it has to have the same structure.”

Shaun’s verdict: “quite strict… but it’s not a bad thing… it gives you cleaner, more predictable code.”
Prev: 082 — Type Basics · Next: 084 — Explicit Types
The auto-transcript mishears a few terms; this narrative uses the corrected forms: the { name, belt, age } ninja demo object carried through every object rule, the rejected skills add-on property (canonical example of the no-new-props rule), Chun-Li as the string seed in the mixed array (transcript spelling varies between “chunley” and “chun-li”), and “override the whole thing” for whole-object reassignment, allowed only with identical structure.