TypeScript Tutorial
TypeScript 2D Arrays
An array of arrays stores a table. Use two indexes: row, then column.
A table under one name
A one-dimensional array is a single row of values. A two-dimensional array is a row of rows: a table. Each inner row has the same element type. You still index from 0.
Annotate it as number[][] (an array of number arrays). The cell at row r and columnc is grid[r][c]. Row first, then column. Mixing that order is the usual bug. C++ writesint grid[2][3] with fixed sizes; TypeScript’s nested arrays can grow.
Declare number[][]
The braces nest the same way the table looks. The outer list wraps the whole array. Each inner list is one row. This grid has two rows and three columns. Print one cell by writing both indexes.
Example
const grid: number[][] = [
[1, 2, 3],
[4, 5, 6],
];
console.log(grid[0][0]);
console.log(grid[1][2]);grid[0][0] is 1, the first cell of the first row. grid[1][2] is 6, the last cell of the second row. There is no grid[2] and no grid[0][3]. Those indexes are off the end and yield undefined at run time — and a type error if tsc can see the tuple length, or a crash later if you call a method on it. Stay inside the bounds you stored.
Walk the table with nested loops
The outer loop runs once per row. The inner loop runs once per column of that row. Print a space between cells and a newline after each row so the output looks like the table you stored.
Example
const grid: number[][] = [
[1, 2, 3],
[4, 5, 6],
];
for (let row = 0; row < grid.length; row++) {
let line = "";
for (let col = 0; col < grid[row].length; col++) {
line += String(grid[row][col]) + " ";
}
console.log(line);
}Compile this at /typescript/try. Change a value in the inner list and print again. Loop bounds follow grid.length and grid[row].length so a new row still prints.
Map indexes to cells
| Expression | Row | Column | Value |
|---|---|---|---|
grid[0][0] | 0 | 0 | 1 |
grid[0][1] | 0 | 1 | 2 |
grid[0][2] | 0 | 2 | 3 |
grid[1][0] | 1 | 0 | 4 |
grid[1][1] | 1 | 1 | 5 |
grid[1][2] | 1 | 2 | 6 |
Assignment uses the same indexes: grid[0][1] = 20; overwrites 2. The outer array is not replaced. That one integer changes.
Fill a grid in a loop
You do not have to list every cell in brackets. This program writes a value into each slot, then prints the table. The stored number is a simple function of the indexes so you can see which cell is which.
Example
const rows = 2;
const cols = 3;
const grid: number[][] = [];
for (let row = 0; row < rows; row++) {
const line: number[] = [];
for (let col = 0; col < cols; col++) {
line.push(row * 10 + col);
}
grid.push(line);
}
for (let row = 0; row < grid.length; row++) {
console.log(grid[row].join(" "));
}Build each inner array, then push it onto grid. Output is 0 1 2 then10 11 12. Initialize every cell before you print it.
Rows can grow
Because this is an array of arrays, you can push a new row. Indexing still uses two brackets: row, then column. Inner rows can be different lengths; this example keeps them equal so it still looks like a rectangle.
Example
const table: number[][] = [
[1, 2, 3],
[4, 5, 6],
];
console.log(table[1][2]);
table.push([7, 8, 9]);
console.log("rows: " + table.length);First line 6. Then rows: 3. That growth is the advantage over a C++int grid[2][3], which cannot gain a row. For a fixed small table, a nested list is still the TypeScript default.
Stay inside both bounds
Valid rows are 0 through grid.length - 1. Valid columns are 0 throughgrid[row].length - 1. Next: const and readonly, which the compilerdoes enforce when a name or a field must not change.