javascript - ¿Es posible combinar los guardias de tipo definidos por el usuario en TypeScript?
dada
type Maybe<T> = T | undefined;
class Obj {
jbo: Maybe<Jbo>;
}
, ¿es posible definir una función que, dado un o: Maybe<Obj>, afirme los tipos tanto de o como de o.jbo?
Estoy pensando en algo como:
function everythingIsDefined(o: Maybe<Obj>):o is Obj && o.jbo is Jbo {
// checks in here
}
Respuesta #1
Un guardia de tipo definido por el usuario solo puede devolver un x es T. Afortunadamente, puedes usar uniones e intersecciones en tu elección de T. Así que, por ejemplo:
function everythingIsDefined(o: Maybe<Obj>): o is Obj & {jbo: Jbo} {
return typeof o !== 'undefined' && typeof o.jbo !== 'undefined';
}
La función everythingIsDefined afirma que la entrada es tanto un Obj (en lugar de undefined), como un objeto cuya propiedad jbo es un Jbo (en lugar de undefined). Entonces puedes usarla así:
if (everythingIsDefined(obj)) {
console.log(obj.jbo.toString()) // no error
}
Respuesta #2
Sí, puedes lograr eso:
type Maybe<T> = T | undefined;
type DeepMaybe<T> = { [K in keyof T]: Maybe<T[K]> };
class Obj {
jbo: Jbo;
}
function everythingIsDefined<T>(o: DeepMaybe<T>): o is T {
return false;
}
Y luego:
let obj: DeepMaybe<Obj> = {} as Obj;
if (everythingIsDefined(obj)) {
// type of obj.jbo is Jbo
} else {
// type of obj.jbo is Maybe<Jbo>
}
(código en el área de juegos)
Explicación:
Probablemente no haya manera de lograr eso con los tipos que proporcionaste (es decir, Obj.jbo: Maybe<Jbo>).
En su lugar, la clase Obj necesita definir sus propiedades como el tipo real, pero si escribes tu variable como DeepMaybe<Obj> (o cualquier otra cosa en lugar de Obj) entonces obtienes lo mismo.
La diferencia ahora es que, debido a que DeepMaybe es un tipo mapeado, tienes mejor control sobre cómo crear la guarda de tipo.
