Cách tránh lỗi gán đối tượng keyof động trong TypeScript


8

Giả sử chúng ta có mã TypeScript trông giống như:

type User = {
  id: number,
  name: string,
}

let user1: User = {id: 123, name: "Hello"};
let user2: User = {id: 456, name: "World"};

let keys: (keyof User)[] = ["id", "name"];

for (let key of keys) {
  user1[key] = user2[key];
}

Điều này gây ra lỗi

Type 'string | number' is not assignable to type 'never'.

cho tuyên bố

user1[key] = user2[key];

Nếu chúng ta thay đổi định nghĩa keysđể

let keys: string[] = ["id", "name"];

lỗi sẽ biến mất, nhưng chúng ta mất loại an toàn.

Có một số cách chúng ta có thể tránh lỗi này trong khi vẫn duy trì an toàn loại?


1
let keys: string[]không xóa lỗi nhưng giới thiệu một lỗi khác, vì không TS không thể đảm bảo rằng user1[key]hoặc user2[key]hợp lệ.
VLAZ

@VLAZ Có, let keys: string[]giới thiệu một vấn đề khác, nhưng đó sẽ là lỗi thời gian chạy (nếu mảng xảy ra có chứa tên trường không tồn tại làm giá trị). Những gì chúng tôi đang tìm kiếm là một kiểm tra thời gian biên dịch để tránh nó.
Vaibhav K

Câu trả lời:


5

Không có cách nào tốt để tránh một loại khẳng định ở đây. Trong phiên bản gần đây trên TS (bài 3.5 tôi nghĩ) khi viết thông qua một chỉ mục, giá trị được viết phải tương thích với tất cả các giá trị thuộc tính có thể được chỉ định bởi khóa. Trong trường hợp của bạn đó sẽ là number & stringgiảm neverdo đó lỗi.

Nguyên nhân sâu xa là TS không theo dõi các biến chỉ của các loại, do đó, liên quan đến các loại, ví dụ của bạn sẽ không khác:

let key1 = 'id' as  keyof User;
let key2 = 'name' as  keyof User;
//Obvious error
user1[key1] = user2[key2] // same error, TS can't distingusih between this and your user1[key] = user2[key]

Giải pháp đơn giản nhất là sử dụng một xác nhận kiểu nếu, như trong trường hợp của bạn, bạn chắc chắn điều này là ổn:

type User = {
  id: number,
  name: string,
}


let user1: User = { id: 123, name: "Hello" };
let user2: User = { id: 456, name: "World" };
for (let key of keys) {
  user1[key] = user2[key] as never
}

Chơi

Ngoài ra (nhưng không phải loại nào an toàn hơn), bạn có thể sử dụng một lỗ hổng nhỏ có thể T[K]gán cho giá trị chỉ mục:

type User = {
  id: number,
  name: string,
}


let user1: User = { id: 123, name: "Hello" };
let user2: User = { id: 456, name: "World" };

let keys: (keyof User)[] = ["id", "name"];

for (let key of keys) {
  set(user1, key, user2[key])
}

Chơi


Cảm ơn vì sự trả lời. Mặc dù không lý tưởng, as neverhoạt động. Ngoài ra, bạn có thể giải thích setphương pháp trong ví dụ thứ hai?
Vaibhav K
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.