Pedro Arantes
Pedro Arantes

Reputation: 5379

Associate elements of an array as the type of a property Typescript

Is there a way to assign the type of a property as the elements of an array? I have the following class:

class SomeClass {
  color: 'red' | 'blue';
}

Is there a way to create an array with the allowed colors and assign it to color type?

class SomeClass {
  color: *some way to get "'red' | 'blue'" from allowedColors*;
  allowedColors = ['red', 'blue'];
}

Upvotes: 0

Views: 467

Answers (2)

Benjamin Schäublin
Benjamin Schäublin

Reputation: 1666

I think it's most common way you declare color to be an enum, and allowedColors should read the allowed values from the enum:

enum Color {
    red,
    blue,
}

private allowedColors: Color[] = Object.keys(Color).map(key => Color[key]);
private color: Color = allowedColors[0];

Upvotes: 1

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249606

By default allowedColors = ['red', 'blue'] will infer the type of allowedColors to be string[], using a trick similar to an old workaround for string based enums we can convince the compiler to type it as ('red'|'blue')[] once we have this we can type color as having the same type as an element of that array:

function arrayTypeHelper<T extends string>(o: Array<T>): T[] {
  return o;
}

class SomeClass {
  static allowedColors = arrayTypeHelper(['red', 'blue']);
  color: typeof SomeClass.allowedColors[0]; // 'red' | 'blue'
}

Or if we don't want to use arrayTypeHelper in multiple places we can just do:

class SomeClass2 {
  static readonly allowedColors = (<T extends string>(o: T[]) => o)(['red', 'blue']);
  color: typeof SomeClass.allowedColors[0]; // 'red' | 'blue'
}

Note I changed allowedColors to be static and readonly as based on the question the field should probably not be mutable and is the same for all instances of the class. Also this is necessary to do the relative typing.

Note 2 While this solution works within the constraint of your current design, maybe you should have a look at string based enums as an alternative.

Upvotes: 1

Related Questions