TypeScript
Completed
-
Section 1: Getting Started
-
Section 2: Basic Types
-
Section 3: Functions and Objects
-
Section 4: Advanced Types
-
Section 5: Object-Oriented TypeScript
-
Section 6: Working with Modules
-
Section 7: Tooling and Practice
-
Section 8: Type-Level Programming
-
Section 9: TypeScript with Backends
-
Section 10: Testing Typed Code
-
Section 11: Data Validation with Types
-
Section 12: Practical Projects
-
Section 13: Compiler Internals
-
Section 14: Configuration Deep Dive
-
Section 15: Enums, Symbols, and Special Types
-
Section 16: Working with Async Code
-
Section 17: TypeScript and the DOM
-
Section 18: Advanced Generics Practice
-
Section 19: Working with Third-Party Types
-
Section 20: Monorepo and Large-Scale Practices
-
Section 21: Common Pitfalls and Best Practices
-
Section 22: Interview Practice
-
Section 23: Handbook: Narrowing In Depth
-
Section 24: Handbook: Object Types In Depth
-
Section 25: Handbook: Classes In Depth
-
Section 26: Handbook: Modules In Depth
-
Section 27: Handbook: Declaration Files In Depth
-
Section 28: JSX and Namespaces
-
Section 29: Compiler Configuration Reference
-
Section 30: More Practice Exercises
-
Section 31: Handbook: Everyday Types Deep Dive
-
Section 32: Utility Types Full Reference
-
Section 33: Decorators Reference
-
Section 34: Mixins and Advanced OOP Patterns
-
Section 35: Iterators and Generators Typing
-
Section 36: More Type-Level Programming Practice
-
Section 37: TypeScript Ecosystem Tools
-
Section 38: TypeScript with Testing Frameworks
-
Section 39: TypeScript for Library Authors
-
Section 40: More Interview Practice
-
Section 41: Handbook: Functions In Depth
-
Section 42: Handbook: Type Manipulation Deep Dive
-
Section 43: More Real-World Patterns
-
Section 44: TypeScript Release Notes Highlights
-
Section 45: Final Practice and Review
8: Arrays and Tuples
How do I actually declare arrays in a way that isn't overkill?
You'll see two main ways to type arrays in TypeScript. The first is the shorthand, like string[], and the second is the generic style, Array<string>. In my experience, almost everyone prefers the shorthand because it's cleaner and easier to read at a glance.
Let's say we're building a simple inventory system for a game. You wouldn't want a player to accidentally put a "Health Potion" (a string) into a list that's supposed to only hold item IDs (numbers). Here is how I'd handle that:
const itemIds: number[] = [101, 402, 505];
const inventoryNames: string[] = ["Iron Sword", "Healing Potion", "Wooden Shield"];
// TypeScript will scream at you if you try this:
// itemIds.push("Magic Wand"); // Error: Argument of type 'string' is not assignable to parameter of type 'number'.
If you have a list that can hold a few different types—say, a log that tracks both the event name and the timestamp—you can use a union type inside the array:
const gameLog: (string | number)[] = ["Game Started", 1625097600, "Player joined", 1625097660];
What's the point of Tuples if they're basically just arrays?
This is a common point of confusion. A regular array is for a list of things where you don't necessarily know the length. A tuple, however, is for when the order and the type of each specific position matter. Think of it like a fixed-length record.
I use tuples all the time for things like coordinates or key-value pairs. For example, if our game character has a position on a 2D map, a tuple is much safer than a generic number[] because it guarantees exactly two values: x and y.
type Position = [number, number];
const playerPos: Position = [10, 25];
const enemyPos: Position = [40, 12];
// This would fail because a Position must have exactly two elements
// const invalidPos: Position = [10, 25, 5];
The real magic happens when you destructure them. Since you know exactly what's at index 0 and 1, the code becomes very predictable.
How do I stop a function from accidentally changing my arrays?
One of the most annoying bugs I've chased is when a function takes an array as an argument and calls .push() or .sort() on it, mutating the original data elsewhere in the app. To prevent this, TypeScript gives us ReadonlyArray (or the readonly modifier).
If you have a list of game constants—like the available difficulty levels—that should never change during runtime, mark them as readonly.
const DIFFICULTY_LEVELS: readonly string[] = ["Easy", "Medium", "Hard", "Nightmare"];
// This will trigger a compiler error
// DIFFICULTY_LEVELS.push("Impossible"); // Error: Property 'push' does not exist on type 'readonly string[]'.
I highly recommend using readonly for any configuration data or props being passed into components. It forces you to create a new array (using the spread operator) if you need to modify the data, which is a much safer pattern in modern JavaScript/TypeScript.
📋 Practical Task
Build a Character Stat and Coordinate Tracker
Create a TypeScript file that implements the following requirements for a game character system:
- Define a tuple type called
RGBColorthat consists of three numbers (representing red, green, and blue). - Create a
readonlyarray calledCHARACTER_CLASSEScontaining "Warrior", "Mage", and "Rogue". - Create a function called
updatePositionthat takes aPositiontuple[number, number]and returns a newPositiontuple with 1 added to both the x and y values. - Create an array called
equipmentthat can hold either strings (item names) or numbers (item power levels).
Ensure that your code compiles without errors and that you've used the readonly modifier to protect your character classes list.
There are no comments for now.