A simple, typesafe way to create multidimensional arrays
Features

🛸 Easily create multidimensional arrays, with as many dimensions as needed 
🎛 Define exact dimensions to create an array of specified size 
🔢 Initialise every point in the array to a custom initial value 
📜 Comes with TypeScript definitions and typesafe returns 
🔬 Tiny size (~ 500 bytes gzipped), with no external dependencies
Installation
Install the package from NPM, and import it into your JavaScript or TypeScript file:
npm install makematrix
import makeMatrix from "makematrix";
Usage
Create a matrix
To simply create an array of n
dimensions, just pass n
as the function's first parameter.
// create a 2D array
const twoDimensionalArray = makeMatrix(2);
// create a 3D array
const threeDimensionalArray = makeMatrix(3);
// create a 4D array
const fourDimensionalArray = makeMatrix(4);
Create a matrix with specified dimensions
To create an array with exact dimensions, pass in an array of numbers.
// create an array of size 5x7
const fiveBySevenArray = makeMatrix([5, 7]);
// create an array of size 3x3x2
const threeByThreeByTwoArray = makeMatrix([3, 3, 2]);
// create an array of size 2x6x9x5x6
const fiveDimensionalArray = makeMatrix([2, 6, 9, 5, 6]);
Initialise the matrix with set values
By default each point in the matrix will be initialised to null
(so that if reading a point returns undefined
, you know that it exists outside the current bounds of the matrix). To fill each point with a custom initial value, pass that value as the function's second parameter, initialValues
:
// create a 3x5 array, with each point equal to 0
const twoDimensionalNumberArray = makeMatrix([3, 5], 0);
// create a 2x6x5 array, with each point equal to "value"
const threeDimensionalStringArray = makeMatrix([2, 6, 5], "value");
Pass a callback for dynamic initial values
The initialValues
parameter can also be a callback, which you can use to dynamically create items for each position in the matrix. The callback can accept an argument which will resolve to the current vector coordinates at each point in the matrix. This can allow you to populate your matrix in a "selfaware" way.
// create a 10x10x10 array, with each point a different random number between 0 and 9
const twoDRandomNumberArray = makeMatrix([10, 10, 10], () => Math.floor(Math.random() * 10));
// create a 5x5 array, with each point self described by a string
const twoDVectorStringArray = makeMatrix([5, 5], (vector) => vector.join());
// create a 7x3,8 array, with each point transformed into a vector object
const twoDVectorObjectArray = makeMatrix([7, 3, 8], (vector) => {
return {
x: vector[0],
y: vector[1],
z: vector[2],
otherData: OTHER_DATA,
}
});
With TypeScript
This package comes with type definitions to provide typesafety when working with the returned arrays.
Returned Matrices will be given a specific type dictated by T
and the number of dimensions, where T
is the type of the value passed to the functions initialValues
parameter (or unknown
, if not set).
For example, a threedimensional array of numbers will be of type number[][][]
. Points within the matrix can then only be reassigned to numbers. TypeScript's compiler will present errors when any reassignments are of the wrong type, including if they are at an incorrect depth in the array. This typesafety also occurs when callbacks are used to dynamically populate your matrix.
const threeDNumberArray = makeMatrix([2, 6, 5], 0); // return type of number[][][]
threeDNumberArray[2][1][2] = 10; // OK
threeDNumberArray[2][1][2] = false; // error: Type 'false' is not assignable to type 'number'
threeDNumberArray[2][1] = 10; // error: Type '"value"' is not assignable to type 'number[]'
threeDNumberArray[2][1][2][0] = 10; // error: Property '0' does not exist on type 'Number'
This typesafety will work for any number of dimensions, however large numbers may slow down your typescript server, due to the nature of the recursive types working under the hood.
Example
To easily create a 3D grid using p5.js, makematrix can be used like below. The source code for the grid at the top of this readme can be seen here, and an interactive demo of it here.
const res = 10; // 10px grid resolution
const matrix = makeMatrix([5, 5, 5]); // A 5x5x5 cube grid
for (let x = 0; x < matrix.length; x += res) {
for (let y = 0; y < matrix[x].length; y += res) {
for (let z = 0; z < matrix[x][y].length; z += res) {
line(x, y, z, x + res, y, z);
line(x, y, z, x, y + res, z);
line(x, y, z, x, y, z + res);
}
}
}
API
// Simple
makeMatrix(dimensions, initialValues);
// With types
makeMatrix<D, T>(
dimensions: number  number[],
initialValues?: T  ((vector: VectorOfLength<D>) => T)
): Matrix<T>;
Parameters

dimensions
— The desired dimensions of the matrix. A number or array of numbers. 
initialValues
— The value that each point in the matrix will initialise to. Can take any value. If a callback is passed, it will be run for each point in the matrix, which will be initialised to the callbacks returned value. (Optional — defaults tonull
).
Returns

Matrix
— A multidimensional array of your desired dimensions, with each point initialised to equal theinitialValues
parameter (or its returned value).
Contributing
This project welcomes contributions. To get started, please open an issue to do discuss the change you'd like to make. Then fork the repo, open it in your editor, and run npm install
in your terminal. This will get everything set up for you to start making changes.
Testing, linting and commit style
This project uses ESLint, Prettier, commitlint and Jest — in combination with lintstaged and Husky — to enforce code quality, consistency and changelog style. These tools will check changed files, and cancel a commit with logging if any of the following are true:
 Eslint has found nonfixable issues in the code
 The Jest testing suites haven't all passed
 The commit message doesn't meet the conventional commit format (run
git cz
in terminal for help formatting your commit message)
Open your git logs to debug commit errors.
License
This package is MIT Licensed.