How to declare array type in TypeScript

In JavaScript, an array is a data structure that allows you to store and manipulate multiple values in a single variable. Arrays can hold elements of different data types, such as numbers, strings, objects, or even other arrays.

const numbers = [1, 2, 3, 4, 5];
const fruits = ['apple', 'banana', 'cherry'];
const mixed = [1, 'apple', true, { name: 'John' }, null];

Arrays in TypeScript are very similar to JavaScript arrays, but TypeScript provides you with the power of static typing, type inference, and type annotations, which can improve code quality and maintainability by catching type-related issues early in the development process.

Keep in mind that TypeScript will automatically determine the type of the array based on its initial values, so you don’t always have to explicitly annotate the type. However, it’s often a good practice to add type annotations for clarity.

There are two main syntaxes to declare an array type in TypeScript:

  • The square bracket notation, such as type[], where type is the element type of the array. For example, string[] is an array of strings, and number[] is an array of numbers.
  • The generic array type, such as Array<type>, where type is the element type of the array. For example, Array<string> is an array of strings, and Array<number> is an array of numbers.
let fruits: string[] = ["apple", "banana", "orange"];
let numbers: Array<number> = [1, 2, 3];

Both syntaxes are equivalent and can be used interchangeably. However, some people prefer the square bracket notation for its simplicity and readability, while others prefer the generic array type for its expressiveness and consistency with other generic types.

Arrays of the same data type

Array contains single data type in TypeScript means that an array can only store values of the same type, such as string[] or number[]. This is different from JavaScript, where an array can have values of different types, such as [1, "message", true]. TypeScript arrays can have a specific type annotation that ensures that only values of that type can be added to the array.

// Annotating an array of numbers
const numbers: number[] = [1, 2, 3, 4, 5];

// Annotating an array of strings
const fruits: string[] = ['apple', 'banana', 'cherry'];

// Annotating an array of booleans
const flags: boolean[] = [true, false, true];

// Annotating an array of objects (with a specific shape)
const persons: { name: string; age: number }[] = [
  { name: 'Alice', age: 30 },
  { name: 'Bob', age: 25 },
  { name: 'Charlie', age: 35 },
];

// Annotating an array of custom types or interfaces
interface Employee {
  id: number;
  name: string;
}

const employees: Employee[] = [
  { id: 1, name: 'John' },
  { id: 2, name: 'Mary' },
];

Arrays of different data types

You can use a union type to specify that each element of the array can be one of several types. For example, (string | number)[] means an array of strings or numbers. You can use this method if you don’t care about the order or length of the array, and you just want to allow multiple types for each element.

const mixedData: (number | string | boolean)[] = [
  1, "apple", true, 2, "banana", false,
];

const mixedDataWithObjects: (number | string | object)[] = [
  1,
  "apple",
  { name: "John" },
  "banana",
  42,
  { city: "New York" },
];

const mixedDates: (Date | string)[] = [
  new Date(),
  "2023-10-25",
  new Date("2022-01-01"),
  "2021-12-31",
];

const mixedFunctions: (Function | string)[] = [
  () => console.log("Function 1"),
  "apple",
  () => console.log("Function 2"),
  "banana",
];

const mixedValues: (number | string | undefined | null)[] = [
  1,
  "apple",
  undefined,
  "banana",
  null,
  42,
];

const mixedSymbols: (boolean | symbol)[] = [
  true,
  Symbol("apple"),
  false,
  Symbol("banana"),
];

interface Person {
  name: string;
  age: number;
}

const mixedCustomTypes: (Person | string)[] = [
  { name: "Alice", age: 30 },
  "Bob",
  { name: "Charlie", age: 25 },
  "David",
];

This kind of array is more flexible and expressive, but it may also introduce errors or bugs if the types are not checked or handled properly.

To safely access and work with the elements of a mixed-type array, consider using type guards or type checking to ensure that you’re dealing with the expected types at runtime. You can use typeof, instanceof, or user-defined type guards.

if (typeof mixedUserData[0] === 'string') {
  // Safely work with the string
}

Arrays of arrays

Arrays of arrays are commonly used in scenarios where you need to store and manipulate structured data, such as grids, tables, matrices, or collections of objects.

A two-dimensional array is an array of arrays, which can be thought of as a grid or matrix. Here’s an example of a 3x3 grid represented as a two-dimensional array:

const grid: number[][] = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
];

A jagged array is an array in which each sub-array can have a different length. This can be useful for representing irregular or sparse data structures:

const jaggedArray: number[][] = [
  [1, 2],
  [3, 4, 5],
  [6]
];

You can create an array of arrays with mixed types as well. For example, an array of arrays containing numbers and strings:

const mixedArray: (number | string)[][] = [
  [1, 'apple'],
  [2, 'banana', 3],
  ['cherry']
];