Nhảy tới nội dung

Read-only array

Trong TypeScript, có thể type annotation cho array là read-only (readonly). Có 2 cách type annotation. Cách thứ nhất là sử dụng từ khóa readonly. Cách thứ hai là sử dụng ReadonlyArray<T>.

readonly T[]

Thêm từ khóa readonly trước type annotation T[] của array sẽ tạo thành kiểu read-only array. Ví dụ, viết readonly number[] thì kiểu của biến đó trở thành read-only array của number.

ts
const nums: readonly number[] = [1, 2, 3];
ts
const nums: readonly number[] = [1, 2, 3];

ReadonlyArray<T>

Cũng có thể viết dạng ReadonlyArray<T> để tạo kiểu read-only array. Ví dụ, nếu muốn array có phần tử kiểu number thành read-only, viết ReadonlyArray<number>.

ts
const nums: ReadonlyArray<number> = [1, 2, 3];
ts
const nums: ReadonlyArray<number> = [1, 2, 3];

Sự khác biệt giữa readonly T[] và ReadonlyArray<T>

Không có sự khác biệt nào giữa readonly T[]ReadonlyArray<T> ngoài cách viết. Chọn cách nào tùy thuộc vào sở thích người viết. Trong team phát triển nên thống nhất sử dụng một cách viết.

Đặc điểm của read-only array

Với read-only array, các method thực hiện thao tác phá hủy (destructive operation) như pushpop sẽ không tồn tại tại thời điểm compile. Do đó, code gọi nums.push(4) trên biến nums kiểu readonly number[] sẽ báo compile error.

ts
const nums: readonly number[] = [1, 2, 3];
nums.push(4);
Property 'push' does not exist on type 'readonly number[]'.2339Property 'push' does not exist on type 'readonly number[]'.
ts
const nums: readonly number[] = [1, 2, 3];
nums.push(4);
Property 'push' does not exist on type 'readonly number[]'.2339Property 'push' does not exist on type 'readonly number[]'.

Điều này chỉ có nghĩa là TypeScript compiler sẽ cảnh báo code cố gắng gọi các method thao tác phá hủy. Không phải là method push bị xóa khỏi array object. Do đó, khi chạy JavaScript, method push vẫn còn.

ts
const nums: readonly number[] = [1, 2, 3];
console.log("push" in nums);
true
ts
const nums: readonly number[] = [1, 2, 3];
console.log("push" in nums);
true

Vì method không bị xóa, nếu bỏ qua compile error và thực thi, vẫn có thể thay đổi array dù là kiểu read-only.

ts
const nums: readonly number[] = [1, 2, 3];
// @ts-ignore
nums.push(4); // Bỏ qua compile error
console.log(nums);
[1, 2, 3, 4]
ts
const nums: readonly number[] = [1, 2, 3];
// @ts-ignore
nums.push(4); // Bỏ qua compile error
console.log(nums);
[1, 2, 3, 4]

Gán read-only array cho array thông thường

Không thể gán read-only array của TypeScript cho array thông thường. Cố gắng gán sẽ báo compile error.

ts
const readonlyNumbers: readonly number[] = [1, 2, 3];
const writableNumbers: number[] = readonlyNumbers;
The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.4104The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
ts
const readonlyNumbers: readonly number[] = [1, 2, 3];
const writableNumbers: number[] = readonlyNumbers;
The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.4104The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.

Điều này là do array thông thường cần các method như pushpop, nhưng read-only array được coi là không có chúng. Nếu thực sự muốn gán read-only array cho array thông thường, có thể sử dụng type assertion.

ts
const readonlyNumbers: readonly number[] = [1, 2, 3];
const writableNumbers: number[] = readonlyNumbers as number[];
ts
const readonlyNumbers: readonly number[] = [1, 2, 3];
const writableNumbers: number[] = readonlyNumbers as number[];

📄️ Type assertion "as"

TypeScript có tính năng ghi đè type inference. Tính năng này được gọi là type assertion.

Ngược lại, có thể gán array thông thường cho read-only array.

Thông tin liên quan

📄️ Thao tác phá hủy của array

Các method của array trong JavaScript có 2 loại: method phá hủy (destructive) và method không phá hủy (non-destructive). Đặc biệt, cần sử dụng cẩn thận các method phá hủy.

📄️ Readonly property của object type

Trong TypeScript, có thể đặt property của object thành read-only. Thêm modifier readonly vào property muốn đặt thành read-only. Khi cố gán giá trị cho property read-only, TypeScript compiler sẽ cảnh báo không thể gán.

📄️ Readonly<T>

Biến tất cả property thành read-only

📄️ Const assertion "as const"

Khi khai báo biến, thêm as const vào cuối sẽ làm cho giá trị đó thành readonly và chuyển thành literal type.