o7planning

TypeScript Tuples Tutorial with Examples

  1. What is Tuple?
  2. Tuple vs Array
  3. Methods

1. What is Tuple?

In TypeScript, a Tuple is a sequence of values. Basically, a Tuple is an array with additional features, here are the characteristics of a Tuple:
  • Tuple is declared with a specific number of elements, and specifies the type for each element.
  • The initial value for the Tuple must be an array with the same number of elements as the declared number of the Tuple.
  • After declaring a tuple and initializing it, you have more freedom to add elements to the Tuple or remove elements from the Tuple.
Syntax:
// Declare a Tuple variable and initialize its value
let myTuple: [dataType1, dataType2, dataTypeN] = [value1, value2, valueN];

// Declare a Tuple variable
let myTuple: [dataType1, dataType2, dataTypeN];
// Initialize its value
myTuple = [value1, value2, valueN];
Example: We create a Tuple with 3 elements of type [string, string, number]:
tuple_ex1.ts
// string: emp number, string: name, number: salary
let myTuple1: [string, string, number] = ['E01', 'Tom', 1200 ]; // OK

let myTuple2: [string, string, number] = ['E01']; // Error !!
let myTuple3: [string, string, number] = ['E01', 'Tom', 1200, 500]; // Error !!
let myTuple4: [string, string, number] = [100, 200, 300]; // Error !!
let myTuple4: [string, string, number] = ['A', 'B', 'C']; // Error !!
A Tuple is actually an object of the Array interface. So we can access its elements through indices.
tuple_ex2.ts
// string: emp number, string: name, number: salary
let myTuple: [string, string, number] = ['E01', 'Tom', 1200 ];

console.log(myTuple);
console.log(`Type: ${myTuple.constructor.name}`); // Array

console.log(`myTuple[0]: ${myTuple[0]}`); // E01
console.log(`myTuple[1]: ${myTuple[1]}`); // Tom
console.log(`myTuple[2]: ${myTuple[2]}`); // 1200

myTuple[1] = 'Jerry';
console.log(myTuple);
Output:
[ 'E01', 'Tom', 1200 ]
Type: Array
myTuple[0]: E01
myTuple[1]: Tom
myTuple[2]: 1200
[ 'E01', 'Jerry', 1200 ]

2. Tuple vs Array

Basically, a Tuple is an array with additional checks.
Tuple's design ideas:
Array
Tuple
Fixed length
No
Yes (*)
Dynamic length
Yes
No (*)
Contains many data types
No
Yes
According to Tuple's design ideas, you should use it when you need an array with a fixed size, and a specific type for each element. However, it is just a loose rule. After declaring and initializing the value for the Tuple, you can change the number of elements of the Tuple if you want.
Example: Use the push() method to add new elements to a Tuple (Although, this is against Tuple's design ideas ).
tuple_warning_ex1.ts (**)
// string: staff number, string: name, number: salary
let staff: [string, string, number] = ['E01', 'Tom', 1200 ];

console.log(staff); // [ 'E01', 'Tom', 1200 ]

let newLength = staff.push('New 1', 'New 2');
console.log('New Length: ' + newLength);  // 5
console.log(staff); // [ 'E01', 'Tom', 1200, 'New 1', 'New 2' ]

// The element at index 3 and 4 cannot be accessed directly:
// console.log(staff[3]); // Compile Error !!!
// console.log(staff[4]); // Compile Error !!!
let idx3 = 3;
let idx4 = 4;
// Accessing the elements at index 3 and 4 in this way is OK:
console.log(staff[idx3]); // OK!
console.log(staff[idx4]); // OK!

// Accessing the elements at index 3 and 4 in this way is OK:
for(let idx in staff) {
    console.log(`Element at ${idx} is: ${staff[idx]}`);
}
Output:
[ 'E01', 'Tom', 1200 ]
New Length: 5
[ 'E01', 'Tom', 1200, 'New 1', 'New 2' ]
New 1
New 2
Element at 0 is: E01
Element at 1 is: Tom
Element at 2 is: 1200
Element at 3 is: New 1
Element at 4 is: New 2
The example below shows that sometimes breaking Tuple's design ideas is beneficial.
tuple_arr_ex1.ts
let employeeInfo: [string, string, number, string] = [
    'E01', // Emp Number
    'Tom', // Emp Name
    1200 , // Salary
    '0901.33333' // Phone Number  
];
employeeInfo.push('0901.44444'); // Second Phone Number
employeeInfo.push('0901.55555'); // Third Phone Number

console.log(employeeInfo);
Output:
[
  'E01',
  'Tom',
  1200,
  '0901.33333',
  '0901.44444',
  '0901.55555'
]

3. Methods

Array methods (and of course it can also be used with Tuples):
Array Interface
interface Array<T> {
  length: number;
  toString(): string;
  toLocaleString(): string;
  pop(): T | undefined;
  push(...items: T[]): number;
  concat(...items: ConcatArray<T>[]): T[];
  concat(...items: (T | ConcatArray<T>)[]): T[];
  join(separator?: string): string;
  reverse(): T[];
  shift(): T | undefined;
  slice(start?: number, end?: number): T[];
  sort(compareFn?: (a: T, b: T) => number): this;
  splice(start: number, deleteCount?: number): T[];
  splice(start: number, deleteCount: number, ...items: T[]): T[];
  unshift(...items: T[]): number;
  indexOf(searchElement: T, fromIndex?: number): number;
  lastIndexOf(searchElement: T, fromIndex?: number): number;
  every<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): this is S[];
  every(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean;
  some(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean;
  forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void;
  map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[];
  filter<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[];
  filter(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): T[];
  reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T;
  reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T;
  reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U;
  reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T;
  reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T;
  reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U;
  [n: number]: T;
}
See examples using the above methods in the article about arrays: