Búsqueda de sitios web

¿Cómo creo un tipo para un arreglo de valores de enumeración con miembros obligatorios en TypeScript?


¿Cómo creo type/interface (AnyColorsWithBlackAndWhite en el ejemplo a continuación) para un array de valores de enum con miembros obligatorios? Necesito que black Y white siempre estén presentes. Intenté intersectar, omitir y extender tanto Array<Color> como Array<Color.black | Color.white> al mismo tiempo, pero hasta ahora no tuve suerte:

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];

Respuesta #1

Veo dos maneras, o creas una función para inferencia y validación o creas una unión de todos los estados permitidos. Primer enfoque:

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

ingresa la descripción del enlace aquí

Segundo :

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

Parque infantil

Como habrás notado, he creado todos los posibles estados de este arreglo. Es mucho: 6!=6 * 5 * 4 * 3 * 2 * 1

TupleUnion genera una combinación de todos los estados permitidos y hace que cada color que no sea blanco o negro sea opcional