Typescript: Crear tipos a partir de valores en una matriz

Creado en 22 oct. 2018  ·  16Comentarios  ·  Fuente: microsoft/TypeScript


Versión de TypeScript: 3.0.3


Términos de búsqueda: escriba según los valores de la matriz

¿Existe una característica actual o planificada para crear un tipo a partir de cadenas en una matriz?

Código

const values = ['A', 'B']
type Foo = OneOf<values> // Is there a way of doing this?

const v1: Foo = 'A' // This should work
const v2: Foo = 'D' // This should give me an error since 'D' doesn't exist in values

Similar a cómo funciona keyof :

const values = {
  A: 'A',
  B: 'B'
}
type Foo = keyof typeof values
const v1: Foo = 'A'
const v2: Foo = 'D' // Type '"D"' is not assignable to type '"A" | "B"'

Asuntos relacionados:https://github.com/Microsoft/TypeScript/issues/20965

Enlace al parque infantil http://www.typescriptlang.org/play/#src = let% 20vals1% 20% 3D% 20% 5B'A '% 2C% 20'B'% 5D% 0D% 0Atype% 20Foo1% 20% 3D% 20OneOf% 3Cvals1% 3E% 20% 2F% 2F% 20Is% 20there% 20a% 20way% 20of% 20haciendo% 20this% 3F% 0D% 0A% 0D% 0Alet% 20v1% 3A% 20Foo1% 20% 3D% 20 ' A '% 20% 2F% 2F% 20This% 20 should% 20work% 0D% 0Alet% 20v2% 3A% 20Foo1% 20% 3D% 20'D'% 20% 2F% 2F% 20This% 20should% 20give% 20me% 20an% 20error% 20since% 20'D '% 20noes% 20exist% 20in% 20values% 0D% 0A% 0D% 0Alet% 20vals2% 20% 3D% 20% 7B% 0D% 0A% 20% 20A% 3A% 20'A '% 2C% 0D% 0A% 20% 20B% 3A% 20'B'% 0D% 0A% 7D% 0D% 0Atype% 20Foo2% 20% 3D% 20keyof% 20typeof% 20vals2% 0D% 0Alet% 20v3% 3A% 20Foo2 % 20% 3D% 20'A '% 0D% 0Alet% 20v4% 3A% 20Foo2% 20% 3D% 20'D'% 20% 2F% 2F% 20Type% 20 '% 22D% 22'% 20is% 20no% 20asignable % 20a% 20 tipo% 20 '% 22A% 22% 20% 7C% 20% 22B% 22'

Question

Comentario más útil

en [email protected] superior. resuélvelo así

export const type = <const>[
  'room',
  'room_with_gifter',
  'user_send'
];

export interface Activity {
  id?: string;
  type: typeof type[number];
}

Todos 16 comentarios

keyof solo funciona porque usa información conocida estáticamente en tiempo de compilación. Los tipos en TS se pueden borrar por completo y no existen en el código transpilado, por lo que simplemente no es posible crear un tipo basado en el contenido de tiempo de ejecución de una matriz.

Esto es posible:

function stringLiterals<T extends string>(...args: T[]): T[] { return args; }
type ElementType<T extends ReadonlyArray<unknown>> = T extends ReadonlyArray<infer ElementType> ? ElementType : never;

const values = stringLiterals('A', 'B');
type Foo = ElementType<typeof values>;

const v1: Foo = 'A' // This should work
const v2: Foo = 'D' // This should give me an error since 'D' doesn't exist in values

Sin embargo, definitivamente no tengo claro cómo hacer esto. # 27179 está relacionado.

Sin embargo, eso sigue usando información conocida estáticamente por el compilador; en ese momento, no entiendo cuál es la ventaja de simplemente decir ”A” | “B” .

@fatcerberus Es útil evitar la repetición de información: si solo escribe const values = ["A", "B"]; type Foo = "A" | "B"; , es fácil que alguien cambie uno de ellos y olvide cambiar el otro. Podría escribir const values: Foo[] =["A", "B"]; , pero aún es susceptible de agregar una entrada adicional a Foo y olvidarse de ponerla en values .

¿Dónde estamos ahora en esto?

Como dijo @ andy-ms, sería realmente útil evitar la repetición de información manualmente.
Y como dijo @fatcerberus , los tipos son completamente borrables. A veces necesitamos verificar los datos en tiempo de ejecución que obtenemos, por ejemplo, de una parte no pura de la aplicación (como el servicio web o del usuario).

Sobre la base de la respuesta de @ andy-ms, y usando las aserciones const introducidas en el mecanografiado 3.4, ahora es posible hacer algo como esto

const values = ['A', 'B'] as const
type ElementType < T extends ReadonlyArray < unknown > > = T extends ReadonlyArray<
  infer ElementType
>
  ? ElementType
  : never

type Foo = ElementType<typeof values> // this is correctly inferred as literal "A" | "B"

Este problema se ha marcado como "Pregunta" y no ha tenido actividad reciente. Se ha cerrado automáticamente por motivos de limpieza. Si todavía está esperando una respuesta, las preguntas suelen ser más adecuadas para stackoverflow .

en [email protected] superior. resuélvelo así

export const type = <const>[
  'room',
  'room_with_gifter',
  'user_send'
];

export interface Activity {
  id?: string;
  type: typeof type[number];
}

En lugar de esto:

export const items = <const>[
  'room',
  'room_with_gifter',
  'user_send'
];

export interface Activity {
  id?: string;
  type: typeof items[number];
}

Puedes hacerlo:

export const items = [
  'room',
  'room_with_gifter',
  'user_send'
] as const;

export type Item = typeof items;

export interface Activity {
  id?: string;
  type: Item;
}

image

_Realmente no me gusta usar type como nombre de variable._

@ 7kms

en [email protected] superior. resuélvelo así

export const type = <const>[
  'room',
  'room_with_gifter',
  'user_send'
];

export interface Activity {
  id?: string;
  type: typeof type[number];
}

Ahora, ¿qué pasa si tengo esto en una clase?

class Class {
  const list = <const>[
   'room',
   'room_with_gifter',
   'user_send'
 ];

 const withType: typeof list[number];
}

No funciona. Tampoco puedo hacer this.list[number] . Además, por mi particular
caso de uso, no puedo establecer list como static

@ 7kms

en [email protected] superior. resuélvelo así

export const type = <const>[
  'room',
  'room_with_gifter',
  'user_send'
];

export interface Activity {
  id?: string;
  type: typeof type[number];
}

Ahora, ¿qué pasa si tengo esto en una clase?

class Class {
  const list = <const>[
   'room',
   'room_with_gifter',
   'user_send'
 ];

 const withType: typeof list[number];
}

No funciona. Tampoco puedo hacer this.list[number] . Además, por mi particular
caso de uso, no puedo establecer list como static

@vegerot No puede usar const directamente en el alcance de class , por lo que la sintaxis es incorrecta.

@ 7kms

en [email protected] superior. resuélvelo así

export const type = <const>[
  'room',
  'room_with_gifter',
  'user_send'
];

export interface Activity {
  id?: string;
  type: typeof type[number];
}

Ahora, ¿qué pasa si tengo esto en una clase?

class Class {
  const list = <const>[
   'room',
   'room_with_gifter',
   'user_send'
 ];

 const withType: typeof list[number];
}

No funciona. Tampoco puedo hacer this.list[number] . Además, por mi particular
caso de uso, no puedo establecer list como static

@vegerot No puede usar const directamente en el alcance de class , por lo que la sintaxis es incorrecta.

@ 7kms Mi mal. Copié y pegué demasiado. Lo que quise decir es

class Class {
  private list = <const>[
   'room',
   'room_with_gifter',
   'user_send'
 ];

 private withType: typeof list[number];

// OR
  private withType2: typeof this.list[number];

}

etc. todos no funcionan.
Además, para mi caso de uso particular, no puedo configurar la lista para que sea estática

@ 7kms

en [email protected] superior. resuélvelo así

export const type = <const>[
  'room',
  'room_with_gifter',
  'user_send'
];

export interface Activity {
  id?: string;
  type: typeof type[number];
}

Ahora, ¿qué pasa si tengo esto en una clase?

class Class {
  const list = <const>[
   'room',
   'room_with_gifter',
   'user_send'
 ];

 const withType: typeof list[number];
}

No funciona. Tampoco puedo hacer this.list[number] . Además, por mi particular
caso de uso, no puedo establecer list como static

@vegerot No puede usar const directamente en el alcance de class , por lo que la sintaxis es incorrecta.

@ 7kms Mi mal. Copié y pegué demasiado. Lo que quise decir es

class Class {
  private list = <const>[
   'room',
   'room_with_gifter',
   'user_send'
 ];

 private withType: typeof list[number];

// OR
  private withType2: typeof this.list[number];

}

etc. todos no funcionan.
Además, para mi caso de uso particular, no puedo configurar la lista para que sea estática

class Class {
  private list = [
    "room",
    "room_with_gifter",
    "user_send"
  ] as const

  private withType: Class["list"][number]
}

@vegerot ¿Qué tal esto?

@eyalch ¡ eso es increíble! Gracias. Pensé que la solución involucraría typeof o algo así. ¿Podría darme una explicación rápida de cómo funciona esto o me vincularía al manual donde se habla de esto?

@eyalch ¡ eso es increíble! Gracias. Pensé que la solución involucraría typeof o algo así. ¿Podría darme una explicación rápida de cómo funciona esto o me vincularía al manual donde se habla de esto?

@vegerot Seguro, creo que es un "tipo de índice". Aquí está en el manual: https://www.typescriptlang.org/docs/handbook/advanced-types.html#index -types

¡Me alegro de haber podido ayudar!

Hola,% username%, si la solución ElementType no funciona para ti también,
preste atención a as const después de la matriz . Es crucial

¿Fue útil esta página
0 / 5 - 0 calificaciones