iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
In TypeScript, a two-dimensional array is an array whose elements are arrays. For example, number[][] represents rows of numbers. You can loop through it with nested indexed loops when you need row and column positions, or nested for...of loops when you only need the values.
How do you create a 2D array in TypeScript?
Declare an array of arrays and give it the type number[][] when each cell should be a number:
const grid: number[][] = [
[1, 2, 3],
[4, 5, 6],
];
The outer array holds rows; each inner array holds the values in one row. The TypeScript Handbook documents T[] as array syntax and Array<T> as an equivalent generic form, so number[][] is equivalent to Array<Array<number>> (Object Types; Everyday Types).
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsHow do you loop through rows and values?
Use indexed loops when you need coordinates
The outer loop selects a row, and the inner loop visits each value in that row. This approach gives you both indices:
#1 Best Overall
for (let row = 0; row < grid.length; row++) {
for (let column = 0; column < grid[row].length; column++) {
console.log(grid[row][column]);
}
}
Use row and column to read or update a cell by position. The inner loop checks the selected row’s own length, so it also works when rows have different numbers of elements.
Use nested for...of loops when you only need values
for (const row of grid) {
for (const value of row) {
console.log(value);
}
}
This form reads directly as “for each row, for each value.” It does not provide row and column indices unless you track them separately.
Rank #2
- TypeScript implements a superset of syntax for strictly typed development, facilitating deep static analysis and enhanced development environment integration. The compiler translates source into standard script formats, ensuring parity across any runtime.
- TypeScript is ideal for front-end developers, full-stack engineers, and software architects who build large-scale web applications. It serves those looking to improve code excellence, reduce bugs through static checking, and maintain complex projects more.
- Lightweight, Classic fit, Double-needle sleeve and bottom hem
What type should you use for a 2D array?
Choose the type from the cell values. Common examples include string[][], boolean[][], and Cell[][] for arrays of objects. Nested arrays are often easiest to read with the shorthand T[][]; Array<Array<T>> expresses the same structure. Google’s TypeScript style guide recommends the shorter nested notation for simple types and allows the generic form when it improves readability for complex types (Google TypeScript Style Guide).
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteUse an interface for a meaningful row type
A numeric index signature can name a row whose numeric positions contain numbers:
interface NumberRow {
[index: number]: number;
}
const grid: NumberRow[] = [
[1, 2, 3],
[4, 5, 6],
];
The name can help when a row has a clear role in the program. The signature says that indexing the row with a number returns a number. For an ordinary numeric grid, number[][] is shorter and communicates the same basic nesting.
Use an interface to describe object cells
When each cell has named properties, define the cell contract and use it as the element type at both array levels:
interface Cell {
value: number;
label: string;
}
const cells: Cell[][] = [
[{ value: 1, label: "A1" }, { value: 2, label: "A2" }],
[{ value: 3, label: "B1" }, { value: 4, label: "B2" }],
];
Here the interface describes each cell, while Cell[][] describes the grid that contains them. An interface is useful for a meaningful object shape; it is not required just to make a basic array type.
Recommended Free Tools
Do 2D array types require equal row lengths?
No. number[][] requires each element of the outer array to be an array of numbers, but it does not require every inner array to have the same length. If your application requires a rectangular grid, check that condition when you receive or construct the data; the type alone does not enforce it.
Best Value
When should you use tuples or readonly arrays?
Use tuples for fixed positions and lengths
A tuple represents a known sequence of positions and types, rather than a general variable-length row. For example, [string, number] describes a pair with a string first and a number second. It is not equivalent to number[][]; [number] is a one-element tuple, not a nested numeric array. The TypeScript Handbook distinguishes tuple syntax from ordinary array types (Everyday Types).
Choose the readonly depth you need
readonly number[][] prevents changes to the outer array through that reference, but the inner rows remain mutable. To make both levels readonly, use readonly (readonly number[])[]. Readonly array types provide a non-mutable view through the typed reference; they do not make the underlying data immutable for every other reference (Object Types).
What do interfaces and array types guarantee at runtime?
Type annotations and interfaces describe types during development; they do not create arrays or validate arbitrary external data at runtime. The TypeScript team explains in its official Walkthrough: Interfaces that “The only job of an interface in TypeScript is to describe a type.” Type information is erased during compilation, so data from an API or other untyped source needs runtime validation if its shape must be trusted.
How do you create rows safely in a loop?
When building a grid procedurally, create a new inner array for each row. If you place the same array reference into multiple outer-array positions, changing one row can appear to change them all because those positions point to the same array.
const rows: number[][] = [];
for (let row = 0; row < 2; row++) {
const values: number[] = [];
for (let column = 0; column < 3; column++) {
values.push(0);
}
rows.push(values);
}
Each pass through the outer loop creates a fresh values array, so the rows can be changed independently.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

