Index Signatures
До Object
у JavaScript (і, отже, TypeScript) можна отримати доступ за допомогою string який містить посилання на будь-який інший JavaScript object.
Ось короткий приклад:
Ми зберігаємо рядок "World"
під ключем "Hello"
. Пам’ятайте, ми сказали, що він може зберігати будь-який object JavaScript, тому давайте збережемо екземпляр класу, щоб показати концепцію:
акож пам’ятайте, що ми сказали, що до нього можна отримати доступ за допомогою string. Якщо ви передаєте будь-який інший об’єкт до сигнатури індексу, середовище виконання JavaScript фактично викликає для нього .toString
перед отриманням результату. Це показано нижче:
Зауважте, що toString
буде викликатися кожного разу, коли obj
використовується в позиції індексу.
Масиви трохи відрізняються. Віртуальні машини JavaScript намагатимуться оптимізувати індексацію за числом (залежно від того, чи це насправді масив, чи збігаються структури збережених елементів тощо). Тому number
слід розглядати як дійсний засіб доступу до об’єкта сам по собі (на відміну від string
). Ось простий приклад масиву:
Отже, це JavaScript. Тепер давайте подивимося, як TypeScript витончено використовує цю концепцію.
TypeScript Index Signature
По-перше, оскільки JavaScript implicitly викликає toString
для будь-якого підпису індексу об’єкта, TypeScript видасть вам помилку, щоб запобігти початківцям стріляти собі в ногу (я бачу, як користувачі стріляють собі в ногу, коли весь час використовують JavaScript на stackoverflow ):
Причина примушування користувача бути явним полягає в тому, що реалізація toString
за замовчуванням для об’єкта є досить жахливою, напр. на v8 завжди повертає [object Object]
:
Звичайно, number
підтримується, оскільки
це необхідно для відмінної підтримки масиву / кортежу.
навіть якщо ви використовуєте його для
obj
, його типова реалізаціяtoString
є гарною (а не[object Object]
).
Пункт 2 показано нижче:
Отже, урок 1:
Сигнатури індексу TypeScript мають бути або
string
абоnumber
Коротка примітка: symbols
також дійсні та підтримуються TypeScript. Але не будемо поки що туди. Маленькі кроки.
Declaring an index signature
Тож ми використовували any
, щоб сказати TypeScript дозволяти нам робити все, що ми хочемо. Насправді ми можемо вказати підпис index явно. наприклад скажімо, ви хочете переконатися, що все, що зберігається в об’єкті за допомогою рядка, відповідає структурі {message: string}
. Це можна зробити за допомогою оголошення { [index:string] : {message: string} }
. Це показано нижче:
ПОРАДА: назва підпису індексу, напр.
index
в{ [index:string] : {message: string} }
не має значення для TypeScript і призначений лише для читабельності. напр. якщо це імена користувачів, ви можете зробити{ [username:string] : {message: string} }
, щоб допомогти наступному розробнику, який перегляне код (яким випадково можете бути ви).
Звичайно, також підтримуються «числові» індекси, напр. { [count: number] : SomeOtherTypeYouWantToStoreEgRebate }
All members must conform to the string
index signature
string
index signatureЯк тільки у вас є підпис індексу string
усі явні члени також повинні відповідати цьому підпису індексу. Це показано нижче:
Це робиться для забезпечення безпеки, щоб будь-який доступ до рядка давав однаковий результат:
Using a limited set of string literals
Сигнатура індексу може вимагати, щоб рядки індексу були членами об’єднання літеральних рядків за допомогою Mapped Types наприклад:
Це часто використовується разом із keyof typeof
для захоплення типів словника, описаного на наступній сторінці.
Специфікація словника може бути відкладена узагальнено:
Having both string
and number
indexers
string
and number
indexersЦе не поширений випадок використання, але компілятор TypeScript все одно підтримує його.
Однак він має обмеження, що індексатор string
є більш суворим, ніж індексатор number
. Це навмисно, напр. щоб дозволити вводити такі речі, як:
Design Pattern: Nested index signature
Розгляд API під час додавання підписів індексу
Досить часто в спільноті JS ви бачите API, які зловживають індексаторами рядків. напр. загальний шаблон серед CSS у бібліотеках JS:
Намагайтеся не змішувати рядкові індексатори з valid значеннями таким чином. наприклад помилка в заповненні залишиться невиявленою:
Натомість відокремте вкладення у власну властивість, наприклад. в назві на зразок nest
(або children
або subnodes
тощо):
Excluding certain properties from the index signature
Іноді потрібно об’єднати властивості в підпис індексу. Це не рекомендовано, і ви повинні uвикористовувати шаблон підпису вкладеного індексу, згаданий вище.
Однак, якщо ви моделюєте existing JavaScript ви можете обійти його за допомогою типу перехрестя. Нижче показано приклад помилки, з якою ви зіткнетеся без використання перехрестя:
Ось обхідний шлях за допомогою типу перетину:
Зауважте, що навіть якщо ви можете оголосити його для моделювання існуючого JavaScript, ви не можете створити такий об’єкт за допомогою TypeScript:
Last updated