Reputation: 5058
How do I create type
/ interface
(AnyColorsWithBlackAndWhite
in example below) for an array of enum values with mandatory members? I need black
AND white
to be always present. I tried to intersect, omit and extend both Array<Color>
and Array<Color.black | Color.white>
at the same time but no luck so far:
enum Color {
red,
green,
yellow,
blue,
black,
white,
}
interface AnyColorsWithBlackAndWhite
extends Array<Color | Color.black | Color.white> {}
export const Correct: AnyColorsWithBlackAndWhite = [Color.red, Color.yellow, Color.black, Color.white];
export const Wrong1: AnyColorsWithBlackAndWhite = [Color.red, Color.yellow];
export const Wrong2: AnyColorsWithBlackAndWhite = [Color.red, Color.yellow, Color.black];
Upvotes: 2
Views: 59
Reputation: 33051
I see two ways, you either create function for inference and validation or you create a union of all allowed states. First approach:
enum Color {
red,
green,
yellow,
blue,
black,
white,
}
type RequiredElements = Color.black | Color.white
const withRequired = <
Item extends Color,
List extends Item[]
>(list: RequiredElements[] extends [...List] ? List : never) => list
const ok = withRequired([Color.red, Color.yellow, Color.black, Color.white]) // ok
const error = withRequired([Color.red, Color.yellow, Color.black]) // error
Second:
enum Color {
red,
green,
yellow,
blue,
black,
white,
}
// https://github.com/microsoft/TypeScript/issues/13298#issuecomment-692864087
type TupleUnion<U extends string | number, R extends any[] = []> = {
[S in U]: Exclude<U, S> extends never
? S extends Color.black | Color.white
? [...R, S] : [...R, S?] : TupleUnion<Exclude<U, S>,
S extends Color.black | Color.white ? [...R, S]
: [...R, S?]
>;
}[U];
type Ok = TupleUnion<Color>
export const Correct: Ok = [Color.red, Color.yellow, Color.black, Color.white]; // ok
export const COrrect1: Ok = [Color.red, Color.white, Color.yellow, Color.black]; // ok
export const Wrong1: Ok = [Color.red, Color.yellow]; // error
export const Wrong2: Ok = [Color.red, Color.green, Color.black]; // error
As you might have noticed, I have created all possible states of this array. It is a lot: 6! = 6 * 5 * 4 * 3 * 2 * 1
TupleUnion
generates a combination of all allowed states and makes every non black and white color as optional
Upvotes: 1