2017-10-23 17 views

Trả lời

3

@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 TKeycụ 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!

+0

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

5

Bạn có thể hạn chế TKey bắt nguồn từ chuỗi hoặc số (sử dụng mở rộng) nhưng điều đó sẽ không thỏa mãn trình biên dịch. index phải là số hoặc chuỗi, không phải là loại chung hoặc bất kỳ loại nào khác cho vấn đề đó. Điều này được ghi lại trong các số language spec

Các vấn đề liên quan