Reputation: 5379
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
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
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