языковая спецификация

вая следующий код ...

type Indexable<TKey, TValue> = { [index: TKey]: TValue }

Это приводит к следующей ошибке:

Тип параметра подписи индекса должен быть «строка» или «число».

Есть ли способ ограничитьTKey быть «строка» или «число»?

Ответы на вопрос(2)

Решение Вопроса

@ TitianCernicova-Драгомир указывает, что вы не можете использоватьTKey как тип в подписи индекса, даже если этоэквивалентноstring или жеnumber.

Если вы знаете, чтоTKey это точноstring или жеnumber, вы можете просто использовать его напрямую и не указыватьTKey в вашем типе:

type StringIndexable<TValue> = { [index: string]: TValue }
type NumberIndexable<TValue> = { [index: number]: TValue }

В стороне: Оказывается, что в куче мест в TypeScript индексный тип для свойств должен бытьstring, и нетnumber, В таких местахnumber обычно рассматривается как своего родаподтип изstring, Это потому, что в JavaScript индексы преобразуются вstring в любом случае, когда вы их используете, это приводит к такому поведению:

const a = { 0: "hello" };
console.log(a[0]); // outputs "hello"
console.log(a['0']) // *still* outputs "hello"

Так как вы не можете использоватьnumber в дальнейшем я буду игнорировать это; если вам нужно использовать цифровые клавиши, TypeScript, вероятно, позволит вам, или вы можете преобразовать вstring вручную. Вернуться к остальной части ответа:

Если вы хотите разрешитьTKey бытьболее конкретно чемstringтолько значениеопределенный ключи разрешены, вы можете использоватьсопоставленные типы:

type Indexable<TKey extends string, TValue> = { [K in TKey]: TValue }

Вы бы использовали его, передавая строковый литерал или объединение строковых литералов для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};

И если вы не хотите ограничивать ключ определенными литералами или объединениями литералов, вы все равно можете использоватьstring какTKey:

const anyNums: Indexable<string, number> = { uno: 1, zwei: 2, trois: 3 };

На самом деле это определение дляIndexable<TKey, TValue> настолько полезен, он уже существует вСтандартная библиотека TypeScript какRecord<K,T>:

type NumNames = 'zero' | 'one' | 'two';
const nums: Record<NumNames, number> = { zero: 0, one: 1, two: 2 };

Поэтому я рекомендую вам использоватьRecord<K,T> для этих целей, поскольку это стандарт, и другие разработчики TypeScript, которые читают ваш код, скорее всего, знакомы с ним.

Надеюсь, это поможет; удачи!

 series0ne23 окт. 2017 г., 14:54
Лучшее решение:StringIndexable а такжеNumberIndexable это именно то, что я в итоге сделал! Очень всеобъемлющий, спасибо.

extends), но это не удовлетворит компилятор.index должен быть числом или строкой, а не универсальным типом или любым другим типом в этом отношении. Это задокументировано вязыковая спецификация

Ваш ответ на вопрос