jackssrt
jackssrt

Reputation: 446

How to make an array of all the strings in string union type?

I want to take type stringUnion = "Value1"|"Value2" and make an array from all the strings in stringUnion

so the array looks like this ["Value1","Value2"], I want an array so I can iterate over it like this:

theArray.map((current, index)=>{

})

How do I do that?

Upvotes: 4

Views: 4115

Answers (3)

Yes, it is possible.

// credits goes to https://stackoverflow.com/questions/50374908/transform-union-type-to-intersection-type/50375286#50375286
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
  k: infer I
) => void
  ? I
  : never;

// credits goes to https://github.com/microsoft/TypeScript/issues/13298#issuecomment-468114901
type UnionToOvlds<U> = UnionToIntersection<
  U extends any ? (f: U) => void : never
>;

type PopUnion<U> = UnionToOvlds<U> extends (a: infer A) => void ? A : never;


// credits goes to https://stackoverflow.com/questions/53953814/typescript-check-if-a-type-is-a-union#comment-94748994
type IsUnion<T> = [T] extends [UnionToIntersection<T>] ? false : true;

type UnionToArray<T, A extends unknown[] = []> = IsUnion<T> extends true
  ? UnionToArray<Exclude<T, PopUnion<T>>, [PopUnion<T>, ...A]>
  : [T, ...A];

interface Person {
  name: string;
  age: number;
  surname: string;
  children: number;
}

type Result = UnionToArray<keyof Person>; // ["name", "age", "surname", "children"]

Here is an alternative way:

// credits goes to https://twitter.com/WrocTypeScript/status/1306296710407352321
type TupleUnion<U extends string, R extends any[] = []> = {
    [S in U]: Exclude<U, S> extends never ? [...R, S] : TupleUnion<Exclude<U, S>, [...R, S]>;
}[U];

interface Person {
    firstName: string;
    lastName: string;
    dob: Date;
    hasCats: false;
}

type keys = TupleUnion<keyof Person>;

Playground

More explanation you can find in my blog

Upvotes: 6

Stevie
Stevie

Reputation: 421

You can't use the stringUnion as a value in a variable (because types are not transpiled to js code).

But if this array is gonna be a constant, you can use:

const stringValues = ["value1", "value2"] as const;
type stringUnion = (typeof stringValues)[number];

Which will allow you to write the values only once.

Upvotes: 2

Lu&#239;s
Lu&#239;s

Reputation: 2833

It is not possible to create a value out of a type. So you can't convert your union type to an array. If you wish to create an array type though. You can do it in 2 ways.

  1. type YourArrayType = StringUnion[];
  2. type YourArrayType = Array<StringUnion>;

This type will create the following type: ("value1" | "value2")[] and it will only allow you to have either "value1" or "value2" in your array with this type.

Upvotes: 0

Related Questions