Vì @TitianCernicova-Dragomir cho biết, bạn không thể sử dụng TKey
làm loại chữ ký chỉ mục, ngay cả khi đó là equivalent to string
or number
.
Nếu bạn biết rằng TKey
là chính xác string
hoặc number
, bạn chỉ có thể sử dụng nó trực tiếp và không xác định TKey
trong loại của bạn:
type StringIndexable<TValue> = { [index: string]: TValue }
type NumberIndexable<TValue> = { [index: number]: TValue }
Ngoài: Nó chỉ ra rằng trong một bó của các địa điểm trong TypeScript, loại chỉ mục cho thuộc tính được yêu cầu là string
và không phải là number
. Ở những nơi như vậy, number
thường được coi là một loại loại phụ trong số string
. Đó là bởi vì trong JavaScript, các chỉ số được chuyển đổi thành string
anyway khi bạn sử dụng chúng, dẫn đến loại hành vi:
const a = { 0: "hello" };
console.log(a[0]); // outputs "hello"
console.log(a['0']) // *still* outputs "hello"
Vì bạn không thể sử dụng number
trong những gì sau, tôi sẽ bỏ qua nó; nếu bạn cần sử dụng các phím số, TypeScript có thể sẽ cho phép bạn hoặc bạn có thể chuyển đổi thành string
theo cách thủ công.Trở lại với phần còn lại của câu trả lời:
Nếu bạn muốn cho phép TKey
là cụ thể hơn hơn string
, có nghĩa là chỉ nhất định phím được cho phép, bạn có thể sử dụng mapped types:
type Indexable<TKey extends string, TValue> = { [K in TKey]: TValue }
Bạn muốn sử dụng nó bằng cách chuyển một chuỗi chữ hoặc liên kết chuỗi ký tự cho TKey
:
type NumNames = 'zero' | 'one' | 'two';
const nums: Indexable<NumNames, number> = { zero: 0, one: 1, two: 2 };
type NumNumerals = '0' | '1' | '2';
const numerals: Indexable<NumNumerals, number> = {0: 0, 1: 1, 2: 2};
Và nếu bạn không muốn để hạn chế chìa khóa để literals, liên hiệp literals Đặc biệt, bạn vẫn có thể sử dụng string
như TKey
:
const anyNums: Indexable<string, number> = { uno: 1, zwei: 2, trois: 3 };
Trong thực tế, định nghĩa này cho Indexable<TKey, TValue>
rất hữu ích , nó đã tồn tại trong TypeScript standard library as Record<K,T>
:
type NumNames = 'zero' | 'one' | 'two';
const nums: Record<NumNames, number> = { zero: 0, one: 1, two: 2 };
vì vậy, tôi khuyên bạn nên sử dụng Record<K,T>
cho những mục đích, vì nó là tiêu chuẩn và các nhà phát triển TypeScript khác đọc mã của bạn có nhiều khả năng quen thuộc hơn với nó.
Hy vọng điều đó sẽ hữu ích; chúc may mắn!
Giải pháp hàng đầu: 'StringIndexable' và' NumberIndexable' là chính xác những gì tôi đã kết thúc! Rất toàn diện, cảm ơn bạn. – series0ne