D
D
djEban2022-02-20 11:59:07
JavaScript
djEban, 2022-02-20 11:59:07

How to make an array type from string literals?

Hello. I want to iterate through string literals and get the array type. How to do it?

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" }]

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
Dmitry Belyaev, 2022-02-20
@bingo347

In TS, there are 2 options to iterate over parts of a union type - these are conditional types and iteration over keys, moreover, iteration over keys is limited by type. number | string | symbol
Conditional types check the condition for each version of the union, which means they allow you to transform each of the options separately:

type MyFunc = <N extends string>() => (N extends string ? Field<N> : never)[];
but the return type will also be a union: It will not work to make a tuple type from a union, since the order is not defined in a union, the type is the same as the type . But you can make a tuple from a tuple:({ name: "town" } | { name: "city" })[]
type MyFunc = <N extends string[]>() => {
    [K in keyof N]: N[K] extends string ? Field<N[K]> : never;
};

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

Well, in real code it is much more convenient when the generic is derived from the arguments, and in order for TS to derive the tuple type from the abstract array itself, this array must be marked with as const, which also makes it a readonly array. But accepting arguments via readonly where we don't need to mutate them is generally good practice. A complete example would look like this:
https://www.typescriptlang.org/play?#code/C4TwDgpg...

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question