137

I've this type:

type myCustomType = "aaa" | "bbb" | "ccc";

I need to convert it to an array like this:

["aaa", "bbb", "ccc"]

How can I do this in typescript?

4
  • 4
    Not possible, types are not in emitted code. But you could do it the other way around - define the array, then create a type from it Commented Jan 22, 2020 at 10:10
  • 3
    @T.J.Crowder const arr = ["aaa", "bbb", "ccc"] as const; type arrTypes = typeof arr[number]; Commented Jan 22, 2020 at 10:14
  • 1
    @CertainPerformance - Ah...I missed out the as const part. I think that would be a good answer, I suggest posting it. Commented Jan 22, 2020 at 10:15
  • 1
    @CertainPerformance Okay thanks for the quick answer. I will go with that solution then - that could also solve my scenario :) Commented Jan 22, 2020 at 10:16

3 Answers 3

143

Types do not exist in emitted code - you can't go from a type to an array.

But you could go the other way around, in some situations. If the array is not dynamic (or its values can be completely determined by the type-checker at the time it's initialized), you can declare the array as const (so that the array's type is ["aaa", "bbb", "ccc"] rather than string[]), and then create a type from it by mapping its values from arr[number]:

const arr = ["aaa", "bbb", "ccc"] as const;
type myCustomType = typeof arr[number];

Here's an example on the playground.

Sign up to request clarification or add additional context in comments.

5 Comments

what does [number] here mean?
It evaluates to the union of arr[0], arr[1], etc; arr[someNumber] where someNumber is a number. It's TypeScript syntax only, not JS.
What means the as const part?
@adrisons It keeps TypeScript from automatically widening the type to string[], and instead keeps it as a static tuple of ["aaa", "bbb", "ccc"]
Fun Fact: You can actually name both the const and the type with the same name. When you import it as a type, TypeScript ensures you cannot use it as a regular array. When you import it as a regular array, TypeScript correctly identifies where it is used as a type and where it is used as a regular array.
11

For example:

  const themeMode = ['light', 'dark'] as const;
  type MainTheme = typeof themeMode[number];
  const values = [...themeMode];

  // iterate on themeMode as const assertion
  values.map((theme) => console.log(theme));

Comments

2

Here is a way of doing this using an intermediary, "throwaway" object, which the compiler will ensure must contain exactly all the possible type values (no more or less):

type myCustomType = "aaa" | "bbb" | "ccc";
const myCustomTypeObject: {
  [key in myCustomType]: undefined;
} = { aaa: undefined, bbb: undefined, ccc: undefined };
const myCustomTypeArray = Object.keys(myCustomTypeObject);

UPDATE: Here is a slightly longer version, which tidies up by setting the intermediary object to undefined afterwards since it is unlikely to be needed again.

type myCustomType = "aaa" | "bbb" | "ccc";
let tempMyCustomTypeObject:
  | {
      [key in myCustomType]: undefined;
    }
  | undefined = { aaa: undefined, bbb: undefined, ccc: undefined };
const myCustomTypeArray = Object.keys(tempMyCustomTypeObject);
tempMyCustomTypeObject = undefined;

4 Comments

Why would we do this? The other answers are much cleaner and don't repeat the strings.
@ADTC The question is asking how to convert a type to an array. As of writing, the accepted answer is saying it can't be done and instead answers the other way round (array=>type). And the other answer is doing similar. In my case, this wasn't useful as I needed to convert a type defined in an external library into an array to be used in a JSON schema. With this solution, the Typescript compilation will fail unless the array is 100% aligned with the type. The intermediary code may not appear "clean" but it's the best I could come up with to address the original question.
It's useful to have this answer, but for your own benefit, why didn't you just simply copy the type from the lib and convert to array manually?
@Ooker Not sure I understood what you mean but the point of the code is to guarantee that the contents of myCustomTypeArray exactly aligns with myCustomType - if you just convert manually without this code, there would be no compiler error if you missed something or e.g. the type was changed by another developer later.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.