openplanning

Tuples trong TypeScript

  1. Tuple là gì?
  2. Tuple vs Mảng
  3. Methods

1. Tuple là gì?

Trong TypeScript, Tuple (bộ dữ liệu) là một dẫy các giá trị. Về cơ bản, Tuple là một mảng với các tính năng bổ xung, dưới đây là các đặc điểm của Tuple:
  • Tuple được khai báo với một số lượng phần tử cụ thể, và chỉ định kiểu cho mỗi phần tử.
  • Giá trị khởi tạo cho Tuple phải là một mảng với số phần tử bằng số phần tử được khai báo của Tuple.
  • Sau khi khai báo một Tuple và khởi tạo giá trị cho nó, bạn có thể tự do hơn trong việc thêm các phần tử vào Tuple hoặc loại bỏ các phần tử ra khỏi Tuple.
Cú pháp:
// 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];
Ví dụ: Chúng ta tạo một Tuple với 3 phần tử kiểu [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 !!
Một Tuple thực sự là một đối tượng của interface Array. Vì vậy chúng ta có thể truy cập vào các phần tử của nó thông qua các chỉ số.
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 Mảng

Về cơ bản Tuple là một mảng cộng với các kiểm tra bổ xung.
Ý tưởng thiết kế của Tuple:
Array
Tuple
Độ dài chính xác
No
Yes (*)
Độ dài động
Yes
No (*)
Chứa nhiều kiểu dữ liệu
No
Yes
Theo ý tưởng thiết kế của Tuple, bạn nên sử dụng nó khi bạn cần một mảng với kích thước cố định, và kiểu cụ thể cho mỗi phần tử. Tuy nhiên đó chỉ là một quy tắc lỏng lẻo, sau khi khai báo và khởi tạo giá trị cho Tuple, bạn có thể thay đổi số lượng phần tử của Tuple nếu muốn.
Ví dụ: Sử dụng phương thức push() để thêm các phần tử mới vào một Tuple (Mặc dù, điều này trái với ý tưởng thiết kế của Tuple).
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
Ví dụ dưới đây cho thấy đôi khi phá vỡ các quy tắc thiết kế của Tuple cũng mang lại lợi ích.
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

Các phương thức của mảng (và tất nhiên nó cũng có thể sử dụng với Tuple):
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;
}
Xem các ví dụ sử dụng các phương thức trên trong bài viết về mảng: