Búsqueda de sitios web

¿Cómo construir un tipo de Typescript a partir de un arreglo de cadenas?


Hasta ahora tengo esto.

export const PacerThemes = ['Default', 'Dark Muted', 'Neon'] as const;
export type PacerTheme = typeof PacerThemes[number];

type ThemeProperties = {
  exhaleHoldBorderColor: string;
  exhaleHoldColor: string;
  inhaleHoldBorderColor: string;
  inhaleHoldColor: string;
};

type Themes = {
  Default: ThemeProperties;
  'Dark Muted': ThemeProperties;
  Neon: ThemeProperties;
};

¿Hay una manera de generar el tipo Themes a partir del arreglo PacerThemes?

Respuesta #1

Podrías usar un tipo mapeado, como se sugiere en los comentarios.

    type ThemeNames = "Default" | "Dark Muted" | "Neon";

    type ThemeProperties = {
      exhaleHoldBorderColor: string;
      exhaleHoldColor: string;
      inhaleHoldBorderColor: string;
      inhaleHoldColor: string;
    };

    type Themes = {
      [T in ThemeNames]: ThemeProperties;
    };

O podrías usar un tipo de utilidad Record

    type ThemeNames = "Default" | "Dark Muted" | "Neon";

    type ThemeProperties = {
      exhaleHoldBorderColor: string;
      exhaleHoldColor: string;
      inhaleHoldBorderColor: string;
      inhaleHoldColor: string;
    }

    type Themes = Record<ThemeNames, ThemeProperties>

Campo de Juegos TS

Respuesta #2

Aquí hay una solución (enlace a Playground):

const PacerThemes = ['Default', 'Dark Muted', 'Neon'] as const


type ThemePropertiesVersion = {
  [k in (typeof PacerThemes)[keyof typeof PacerThemes & number]]: "YourType"
}

Si quieres hacer esto más genérico introduciendo algunos tipos auxiliares reutilizables, podrías encontrarte con el problema de que readonly any[] no se extiende a any[].

Por ejemplo, esto no funcionaría, ya que typeof PacerThemes es readonly:

type Items<A extends any[]> = A[keyof A & number]

Para manejar esto podrías hacer algo como esto (enlace de Playground):

const PacerThemes = ['Default', 'Dark Muted', 'Neon'] as const


// Version 1 -- allow only readonly arrays

type ReadonlyItems<P extends readonly any[]> = P[keyof P & number]

type TestVersion1 = NonRestrictiveItems<typeof PacerThemes>

type ThemePropertiesVersion1 = {
  [k in ReadonlyItems<typeof PacerThemes>]: "YourType"
}


// Version 2 -- allow both

type NonRestrictiveItems<P extends (readonly any[]) | any[]> = P[keyof P & number]

type TestVersion2 = NonRestrictiveItems<typeof PacerThemes>

type ThemePropertiesVersion2 = {
  [k in NonRestrictiveItems<typeof PacerThemes>]: "YourType"
}