resolvejsonmodule - typescript multiple types
¿Hay un `valueof` similar a` keyof` en TypeScript? (2)
Quiero poder asignar una propiedad de objeto a un valor dado una clave y un valor como entradas y aún así poder determinar el tipo del valor. Es un poco difícil de explicar, por lo que este código debería revelar el problema:
type JWT = { id: string, token: string, expire: Date };
const obj: JWT = { id: ''abc123'', token: ''tk01'', expire: new Date(2018, 2, 14) };
function print(key: keyof JWT) {
switch (key) {
case ''id'':
case ''token'':
console.log(obj[key].toUpperCase());
break;
case ''expire'':
console.log(obj[key].toISOString());
break;
}
}
function onChange(key: keyof JWT, value: any) {
switch (key) {
case ''id'':
case ''token'':
obj[key] = value + '' (assigned)'';
break;
case ''expire'':
obj[key] = value;
break;
}
}
print(''id'');
print(''expire'');
onChange(''id'', ''def456'');
onChange(''expire'', new Date(2018, 3, 14));
print(''id'');
print(''expire'');
onChange(''expire'', 1337); // should fail here at compile time
print(''expire''); // actually fails here at run time
Intenté cambiar
value: any
a
value: valueof JWT
pero eso no funcionó.
Idealmente,
onChange(''expire'', 1337)
fallaría porque
1337
no es un tipo de fecha.
¿Cómo puedo cambiar el
value: any
para que sea el valor de la clave dada?
ACTUALIZACIÓN: Parece que el título de la pregunta atrae a las personas que buscan una unión de todos los tipos de valores de propiedad posibles, de forma análoga a la forma en que
keyof
le brinda la unión de todos los tipos de clave de propiedad posibles.
Ayudemos a esas personas primero.
Puede hacer un
ValueOf
análogo a
keyof
, utilizando
tipos de búsqueda
con
keyof T
como la clave, de esta manera:
type ValueOf<T> = T[keyof T];
que te da
type Foo = { a: string, b: number };
type ValueOfFoo = ValueOf<Foo>; // string | number
Para la pregunta que se indica, puede usar claves individuales, más estrechas que la
keyof T
, para extraer solo el tipo de valor que le interesa:
type sameAsString = Foo[''a'']; // lookup a in Foo
type sameAsNumber = Foo[''b'']; // lookup b in Foo
Para asegurarse de que el par clave / valor "coincida" correctamente en una función, debe usar generics y tipos de búsqueda, como este:
declare function onChange<K extends keyof JWT>(key: K, value: JWT[K]): void;
onChange(''id'', ''def456''); // okay
onChange(''expire'', new Date(2018, 3, 14)); // okay
onChange(''expire'', 1337); // error. 1337 not assignable to Date
La idea es que el parámetro
key
permite al compilador inferir el parámetro
K
genérico.
Luego requiere que el
value
coincida con
JWT[K]
, el tipo de búsqueda que necesita.
Espero que ayude; ¡buena suerte!
Si alguien todavía busca la implementación de
valueof
para algún propósito, este es uno que se me ocurrió:
type valueof<T> = T[keyof T]
Uso:
type actions = {
a: {
type: ''Reset''
data: number
}
b: {
type: ''Apply''
data: string
}
}
type actionValues = valueof<actions>
Funciona como se espera :) Devuelve una unión de todos los tipos posibles