Di que tengo una lista
const list = ['a', 'b', 'c']
¿Es posible derivar de este tipo de unión de valores que es 'a' | 'b' | 'c'
?
Quiero esto porque quiero definir el tipo que permite solo valores de la matriz estática, y también necesito enumerar estos valores en tiempo de ejecución, por lo que uso matriz.
Ejemplo de cómo se puede implementar con un objeto indexado:
const indexed = {a: null, b: null, c: null}
const list = Object.keys(index)
type NeededUnionType = keyof typeof indexed
Me pregunto si es posible hacerlo sin usar un mapa indexado.
typescript
EL COLOR BLANCO
fuente
fuente
Respuestas:
ACTUALIZACIÓN Feb 2019
En TypeScript 3.4, que debería lanzarse en marzo de 2019 , será posible decirle al compilador que infiera el tipo de una tupla de literales como una tupla de literales , en lugar de, por ejemplo,
string[]
utilizando laas const
sintaxis . Este tipo de afirmación hace que el compilador infiera el tipo más estrecho posible para un valor, incluido hacer todoreadonly
. Debe tener un aspecto como este:const list = ['a', 'b', 'c'] as const; // TS3.4 syntax type NeededUnionType = typeof list[number]; // 'a'|'b'|'c';
Esto evitará la necesidad de una función auxiliar de cualquier tipo. ¡Buena suerte de nuevo a todos!
ACTUALIZACIÓN Julio 2018
Parece que, a partir de TypeScript 3.0, será posible que TypeScript infiera automáticamente tipos de tuplas . Una vez que se lanza, la
tuple()
función que necesita se puede escribir sucintamente como:export type Lit = string | number | boolean | undefined | null | void | {}; export const tuple = <T extends Lit[]>(...args: T) => args;
Y luego puedes usarlo así:
const list = tuple('a','b','c'); // type is ['a','b','c'] type NeededUnionType = typeof list[number]; // 'a'|'b'|'c'
¡Espero que funcione para la gente!
ACTUALIZACIÓN Diciembre de 2017
Desde que publiqué esta respuesta, encontré una manera de inferir tipos de tuplas si está dispuesto a agregar una función a su biblioteca. Consulte la función
tuple()
en tuple.ts . Al usarlo, puede escribir lo siguiente y no repetirlo:const list = tuple('a','b','c'); // type is ['a','b','c'] type NeededUnionType = typeof list[number]; // 'a'|'b'|'c'
¡Buena suerte!
ORIGINAL Julio de 2017
Un problema es que el literal
['a','b','c']
se inferirá como tipostring[]
, por lo que el sistema de tipos se olvidará de los valores específicos. Puede forzar al sistema de tipos a recordar cada valor como una cadena literal:const list = ['a' as 'a','b' as 'b','c' as 'c']; // infers as ('a'|'b'|'c')[]
O, quizás mejor, interprete la lista como un tipo de tupla:
const list: ['a','b','c'] = ['a','b','c']; // tuple
Esta es una repetición molesta, pero al menos no introduce un objeto extraño en tiempo de ejecución.
Ahora puede obtener su sindicato así:
type NeededUnionType = typeof list[number]; // 'a'|'b'|'c'.
Espero que ayude.
fuente
cont xs = ['a','b','c']; const list = tuple(...xs);
const xs = ['a','b','c']
el compilador ya se ha ampliadoxs
astring[]
y completamente olvidado de los valores específicos. No puedo evitar ese comportamiento al menos a partir de TS3.2 (aunque podría haber unaas const
notación futura que funcione). De todos modos, creo que la respuesta tal como está sigue siendo tan correcta como puedo hacerlo (menciono allí que['a','b','c']
se infierestring[]
), así que no estoy seguro de qué más necesita.[number]
hacelist[number]
?(typeof list)[number]
... notypeof (list[number])
. El tipoT[K]
es un tipo de búsqueda que obtiene el tipo de propiedad deT
cuya clave esK
. En(typeof list)[number]
, obtienes los tipos de propiedades de(typeof list)
cuyas claves sonnumber
. Las matricestypeof list
tienen firmas de índice numérico , por lo que sunumber
clave produce la unión de todas las propiedades indexadas numéricamente.Actualización para TypeScript 3.4:
Una nueva sintaxis llamada "contextos const" que llegará a TypeScript 3.4 permitirá una solución aún más simple que no requiere una llamada de función como se demostró. Esta característica se encuentra actualmente en revisión como se ve en este PR .
En resumen, esta sintaxis permite la creación de matrices inmutables que tienen un tipo estrecho (es decir, el tipo en
['a', 'b', 'c']
lugar de('a' | 'b' | 'c')[]
ostring[]
). De esta manera, podemos crear tipos de unión a partir de literales tan fácil como se muestra a continuación:const MY_VALUES = <const> ['a', 'b', 'c'] type MyType = typeof MY_VALUES[number]
En sintaxis alternativa:
const MY_VALUES = ['a', 'b', 'c'] as const type MyType = typeof MY_VALUES[number]
fuente
No es posible hacer esto con Array.
La razón es que, incluso si declara la variable como constante, el contenido de una matriz aún puede cambiar, por lo que @jonrsharpe menciona que esto es tiempo de ejecución.
Dado lo que desea, puede ser mejor usarlo
interface
conkeyof
:interface X { a: string, b: string } type Y = keyof X // Y: 'a' | 'b'
O bien
enum
:fuente
a
campo ..Pick<T, U>
para eso.