> ## Content Index
> Fetch the complete content index at: https://danielbarta.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# How to list the possible values of a string literal union type in TypeScript
- URL: https://danielbarta.com/literal-iteration-typescript/
- Published: 2022-04-25T12:00:00.000Z
- Updated: 2026-06-22T01:18:08.000Z
- Description: String literals are one of the most straightforward and powerful tools of TypeScript. But until v3.4, it was impossible to list its accepted values. Developers needed to fall back to enums. Not a problem anymore.
- Author: Daniel Barta
- Tags: TypeScript, #Import 2023-04-16 20:09, #Import 2026-10-23 10:14

String literals are one of the most straightforward and powerful tools of TypeScript. But until v3.4, it was impossible to list its accepted values. Developers needed to fall back to enums. Not a problem anymore.

On an imaginary page, there is a certain set of user types, namely `Admin`, `Editor`, `Reader` and `Anonymous`. The `UserType` is defined the following way.

```typescript
type UserType = 'Admin' | 'Editor' | 'Reader' | 'Anonymous';
```

What if, for any purposes, we need to list all the values this type might take?

## TL;DR

The solution is

```typescript
export const UserTypes = ['Admin', 'Editor', 'Reader', 
'Anonymous'] as const; 
type UserType = typeof UserTypes[number]; 
```

![](https://danielbarta.com/content/images/2022/04/lazy.gif)

## Breakdown

It is not possible iterate on a type, but there is one type where we certainly can.

```typescript
export const UserTypes = ['Admin', 'Editor', 'Reader', 'Anonymous'];
```

Now we have an array, what we can iterate through, but we don't have a type anymore. So we need to make a type, that takes the values from this array. Let's try the following code.

```typescript
export const UserTypes = ['Admin', 'Editor', 'Reader', 'Anonymous'];
type UserType = typeof UserTypes[0] | typeof UserTypes[1] | typeof UserTypes[2] | typeof UserTypes[3]; // result: UserTypes: string[]

```

It is not elegant; if we need to add a new type of user, we have to add it in two places; once in the array and once in the type. 

But the bigger problem is, the type `UserType` is just an array of string. In other words, the type we created takes in every string, from a mistyped `editr` to a `superadmin` type.

When we define an array as we did, the compiler looks at the values and says it is an array of strings. We can add, remove and edit elements as long as all the elements are strings. But this is not what we want now. We need to tell the compiler that this is not an array of any strings but an array that contains the elements `Admin`, `Editor`, `Reader`, and `Anonymous`. That implies that we don't want to change the order of the elements, edit, or remove anything in runtime. We can use the [const assertion](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html?ref=danielbarta.com#const-assertions).

```typescript
export const UserTypes = ['Admin', 'Editor', 'Reader', 
'Anonymous'] as const 
// result UserTypes: readonly ['Admin', 'Editor', 'Reader', 'Anonymous'];

type UserType = typeof UserTypes[0] | typeof UserTypes[1] | typeof UserTypes[2] | typeof UserTypes[3]; 
// result: type UserType = "Admin" | "Editor" | "Reader" | "Anonymous"
```

Now, if I try to add a type `superadmin`, I get an error: *'Property 'add' does not exist on type 'readonly \["Admin", "Editor", "Reader", "Anonymous"\]'.'*

Finally, the `UserType` is exactly what we want, and now we have an array to iterate on. The only problem is the hard-coded indexing in the type definition. Fortunately, there is a shortcut for this too.

```typescript
export const UserTypes = ['Admin', 'Editor', 'Reader', 
'Anonymous'] as const 
// result UserTypes: readonly ['Admin', 'Editor', 'Reader', 'Anonymous'];

type UserType = typeof UserTypes[number]; 
// result: type UserType = "Admin" | "Editor" | "Reader" | "Anonymous"
```

`typeof UserTypes[number]` tells the compiler to get the types of values from UserTypes, that can be retrieved using any possible number.

## Summary

- We defined an array for the values that the `UserType` can take.
- This array exists in runtime too so we can log, or show these values on the screen.
- Using this array we were able to define our `UserType`