Cómo utilizar uniones discriminadas con clases
Estoy tratando de convertir una unión discriminada en una cadena de texto. La unión discriminada consiste en dos interfaces. Si llamo a la función con un objeto simple que coincide con una de las interfaces, obtengo el resultado esperado. Si llamo a la función con una clase que implementa la interfaz, obtengo undefined
como resultado. ¿Puedes explicarme este comportamiento? ¿Y hay alguna forma de solucionarlo?
interface Foo {
kind: 'pending',
myVar: string
}
interface Bar {
kind: 'running',
myVar2: string
}
type FooBarUnion = Foo | Bar;
class FooClass implements Foo {
kind: 'pending'
myVar: string
constructor(text) {
this.myVar = text;
}
}
function fbuToString(o: FooBarUnion) {
switch (o.kind) {
case "pending": return `O está pendiente. ${o.myVar}`;
case "running": return `O está en ejecución. ${o.myVar2}`;
}
}
// imprime undefined
console.log(fbuToString(new FooClass('test')));
// imprime el resultado esperado
console.log(fbuToString({ kind: 'pending', myVar: 'test' }));
Estoy ejecutando este archivo con ts-node nombreDeArchivo.ts
.
davy.ai
La razón por la que llamar a la función con
new FooClass('test')
devuelveundefined
es porqueFooClass
no implementa explícitamenteBar
. Por lo tanto, cuando la instrucción switch llega a la ramacase "running"
, no sabe cómo manejar el objetoFooClass
y devuelveundefined
.Una forma de solucionar esto es hacer que
FooClass
implemente tantoFoo
comoBar
, incluso si realmente no utiliza la propiedadmyVar2
deBar
. Otra posibilidad es agregar un guardia de tipo a la ramacase "running"
para verificar si el objeto es una instancia deBar
. Por ejemplo:Esto verifica si la propiedad
myVar2
existe eno
, lo que significaría que es una instancia deBar
, y devuelve la cadena esperada.