TypeScript Basics (III): Arrays

James Ng
5 min readNov 16, 2022
TypeScript logo

Time for the most common data structure to get “typed” up — arrays.

Type annotation for arrays can be assigned by simply putting a set of square brackets “[ ]” after the element type. Another syntax that can be used is Array<type>. Here are some examples:

let nums1: number[] = [1, 2, 3, 4, 5];
let nums2: Array<number> = [6, 7, 8, 9, 10];

Once the array is type annotated, TypeScript safeguards against different data types from being associated with it. In the first example, nums is declared as an array type of number and cannot be assigned strings.

Additionally, non-number elements cannot be added to the array.

Multi-Dimensional Arrays

Multi-dimensional arrays, meaning an array of arrays, can be declared by simply adding another set of square brackets “[ ]” to the original syntax.

// Notice the double square brackets
let nums: number[][] = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ];

The empty array “[ ]” will not cause errors when assigned to any array type.

// No errors for the following:
let nums: number[] = [];
let strings: string[] = [];
let booleans: boolean[] = [];

Tuples

Arrays can have multiple data types as elements. A tuple is a data structure with specified length and order of data types for its elements. While there is no default tuple in JavaScript, leave it for TypeScript to “type” it up. Tuple types are annotated with an array of data types in a specific order.

/* 
tuple of length 4 contains a number, string, boolean, and number
in that order specific order
*/
let tuple: [number, string, boolean, number] = [ 23, 'string', true, 32 ];

TypeScript throws errors when incorrect data types are assigned in the specified order and when the length is not exact.

Despite the similarities between tuples and arrays, they are not compatible types in TypeScript. If an array with the same (ordered) data types and length is assigned to a tuple variable, TS will throw a fit. Remember, it is pretty strict.

Array Type Inference

While TypeScript can infer variable types from initial values and return statements, things are slightly different when dealing with arrays. Let’s say we declare a variable nums as the following:

let nums = [1, 2, 3];

This looks like it could possibly be inferred as an array type number[ ] or tuple type [ number, number, number ]. TypeScript gives the nod to the less restrictive type — the array type. Less restrictive!? 😱

let nums = [1,2,3]; // Infers array type: number[]
nums[3] = 4; // No error
console.log(nums); //-> [1,2,3,4]

Interestingly, TS will infer an array type number[ ] when the .concat( ) method is used on a tuple of numbers.

let tuple: [number, number] = [123, 456];
let tupleWannaBe = tuple.concat([789]) // Infers array type: number[]
console.log(tupleWannaBe) //-> [123, 456, 789]

Rest Parameter & Spread Syntax

The rest parameter syntax allows for an unlimited number of arguments to be passed in a function. Basically, the “rest of the parameters” are packaged in an array. It is represented with the spread syntax “…arguments” and can ONLY be the last parameter in a function.

// Rest parameter -> ...arguments
const function = (a, b, c, ...arguments) => { code };

Since the rest parameter is an array of arguments, then TypeScript allows for type annotation to ensure the right arguments are passed through. A “string” trying to sneak into a “number” party? No funny business!

Sometimes there are many specific argument types passed in a function and it can be quite cumbersome to type out each specific type. For example, the function cakeMaker calls for the following parameters:

function cakeMaker(
servingSize: number,
cakeSizeInInches: number,
cakeType: string,
occassion: string,
wantCandles: boolean,
pickUpDay: string
) = { code }

That is a lot to “type” — no pun intended.

Instead, we can refactor by using a tuple variable to represent all the specific data types and use the spread syntax to make the code more concise and readable.

let cakeDetails: [number, number, string, string, boolean, string] = 
[ 8, 6, 'Strawberry ShortCake', 'birthday', true, 'Saturday' ];

cakeMaker(...cakeDetails);

Summary

Array types can be declared after variable name with a type followed by square bracket “[ ]”, e.g., string[ ] or Array<string>.

Multi-dimensional array (an array of arrays) types are type annotated with an additional square bracket, e.g., number[ ][ ].

Tuple types have specified length and order of data types for its elements, e.g., [ number, string, boolean ].

Array types can be inferred as well. When an array that contains uniform data type is declared ( e.g, let nums = [1,2,3] ), TypeScript infers that it is an array type — number[ ] as opposed to a tuple type — [number, number, number].

Rest parameter can be annotated as a specific type with an array type syntax. Spread syntax can be used to refactor code for functions that take in a lot of parameters.

Credit & Inspiration: Codecademy’s Learn TypeScript course

--

--

James Ng

Software engineer, math & physics educator, mentor