@nicknamemyy

Как в typescript правильно описать интерфейс?

Есть массив виду ['значение1', 'значение2', 'значение3'];
нужно, чтобы значением было одно из того, что есть в массиве, типа такого:
interface MyInterface {
     name: 'значение1' | 'значение2' | 'значение3';
}
  • Вопрос задан
  • 188 просмотров
Пригласить эксперта
Ответы на вопрос 1
@forspamonly2
вообще-то можно. но вопрос это не простой ни разу.

в распоследнем тайпскрипте 3.4 появилась возможность поставить массиву модификатор as const, который сделает из него tuple с константами.

взяв с typeof его тип, от него можно будет с помощью keyofполучить index type - объединение имён всех его полей, а потом взять от него типы самих полей квадратными скобкaми, и там будут все ваши строчки.

на другие строчки оно уже начнёт ругаться. проблема в том, что кроме строчек там будут ещё и все методы и свойства массива. от этого ругань получится невразумительная, и кроме строчек будет подходить, например, число - длина того массива. ну и функции из прототипа массива, хотя вы вряд ли станете их присваивать своим полям.

чтобы оставить только строки, придётся использовать ещё и conditional type (снова в сочетании с mapped и index types): опять получить полное объединение имён полей, пройти по всем полям, получить тип, и если это строка - взять имя поля, а если нет - взять never. и результат выбирать уже по отфильтрованному объединению имён полей - по never ничего не выбирается.

const x = ['значение1', 'значение2', 'значение3'] as const;

type AllValuesOfX = (typeof x)[keyof typeof x];

const tst1_1:AllValuesOfX = 'значение1';
const tst1_2:AllValuesOfX = 'значение4'; //error TS2322: Type '"значение4"' is not assignable to type '"значение1" | "значение2" | "значение3" | 3 | (() => string) | (() => string) | { (...items: ConcatArray<"значение1" | "значение2" | "значение3">[]): ("значение1" | "значение2" | "значение3")[]; (...items: ("значение1" | ... 2 more ... | ConcatArray<...>)[]): ("значение1" | ... 1 more ... | "значение3")[]; } | ... 1...'.
const tst1_3:AllValuesOfX = 3;
const tst1_4:AllValuesOfX = Array.prototype.map;

type StringProperties<T> = { [K in keyof T]: T[K] extends string ? K : never }[keyof T];
type StringsFromX = (typeof x)[keyof StringProperties<typeof x>];

const tst2_1:StringsFromX = 'значение2';
const tst2_2:StringsFromX = 3; // error TS2322: Type '3' is not assignable to type '"значение1" | "значение2" | "значение3"'.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы