@djEban

Как из строковых литералов сделать тип массива?

Всем привет. Хочу проитерироваться через строчные литералы и получить тип массива. Как это сделать?

type Field<N extends string> = {
  name: N;
}

type MyFunc = <N extends string>() => Array<each Name in N { Field<Name> }> // нужно вот тут вернуть массив (фековый синтаксис сейчас) 

const myFunc: MyFunc = () => [];

myFunc<"town" | "city">(); // возвращаемый тип должен быть [{ name: "town" }, { name: "city" }]
  • Вопрос задан
  • 88 просмотров
Пригласить эксперта
Ответы на вопрос 1
bingo347
@bingo347 Куратор тега JavaScript
Crazy on performance...
В TS есть 2 варианта итерироваться по частям юнион типа - это условные типы и итерация по ключам, притом итерация по ключам ограничена типом number | string | symbol

Условные типы проверяют условие для каждого варианта юниона, а значит позволяют трансформировать каждый из вариантов по отдельности:
type MyFunc = <N extends string>() => (N extends string ? Field<N> : never)[];
но возвращаемый тип так же будет юнионом:({ name: "town" } | { name: "city" })[]

Сделать кортежный тип из юниона не выйдет, так как в юнионе не определен порядок, тип "town" | "city" это тоже самое, что и тип "city" | "town".
Но можно сделать кортеж из кортежа:
type MyFunc = <N extends string[]>() => {
    [K in keyof N]: N[K] extends string ? Field<N[K]> : never;
};

myFunc<["town", "city"]>()


Ну и в реальном коде гораздо удобнее, когда дженерик выводится из аргументов, а для того что бы TS сам вывел кортежный тип из абстрактного массива, данный массив нужно помечать as const, что так же делает его readonly массивом. Но принимать аргументы через readonly там где нам не нужно их мутирорвать - это вообще хорошая практика. Полный пример будет выглядеть так:
https://www.typescriptlang.org/play?#code/C4TwDgpg...
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы