Sergino
Sergino

Reputation: 10838

How to iterate typescript string literal?

I have this literal type export type names = 'n1' | 'n2' | 'n3' | 'n4' | 'n5' | 'n6';

I wonder how would you iterate that type ?

May be you can convert that type in something else and iterate that?

Should you redefine the type in a different way?

names.forEach(value => {
  console.log(value);
}); 

Upvotes: 2

Views: 1237

Answers (2)

Shaun Luttin
Shaun Luttin

Reputation: 141622

Short Answer

You could define it as a const and a type like this:

const names = ['n1' , 'n2' , 'n3' , 'n4' , 'n5' , 'n6'] as const;

// This produces the union type 'n1' | 'n2' | 'n3' | 'n4' | 'n5' | 'n6';
type names = typeof names[number];

// use names as a type here
const n1: names = 'n1';

console.log({
  names,
  n1,
  // use names as an array here
  mapped: names.map(name => `I am ${name}`)
});

Explanation and Demo

What is going on here?

The as const creates an array with a const context. That means the array is not a string array but is a readonly array of specific string literal values.

Then, the typeof names[number] uses an indexed access operator to extract those string literal values into a union type.

If we did not use as const to define our array, then the typeof names[number] would give us string type instead of a union of the array's string literal values.

The end result is pretty neat. We can use names as a union type for type checking and as an array at runtime.

Here it is in the playground, and here is the playground output in JavaScript:

"use strict";
const names = ['n1', 'n2', 'n3', 'n4', 'n5', 'n6'];
const n1 = 'n1';
console.log({
names,
n1,
mapped: names.map(name => `I am ${name}`)
});

Caveat: The use of names as both a union type an an array value raises a question about naming conventions. Usually types are PascalCased (e.g. Names) and values are camelCased (e.g. names). Which naming conventions ought we to follow here?

For completeness, here is how it looks in VS Code across two files:

enter image description here

Upvotes: 8

CertainPerformance
CertainPerformance

Reputation: 371019

Types do not exist in the compiled code - there is nothing emitted to iterate over.

If you need the union type as shown in the question and need to be able to iterate over it as an array, first create the array as const, and define the type as the array's values:

const arr = ['n1', 'n2', 'n3', 'n4', 'n5', 'n6'] as const;
export type names = typeof arr[number];
for (const num of arr) {
  console.log(num);
}

Upvotes: 3

Related Questions