es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

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.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    La razón por la que llamar a la función con new FooClass('test') devuelve undefined es porque FooClass no implementa explícitamente Bar. Por lo tanto, cuando la instrucción switch llega a la rama case "running", no sabe cómo manejar el objeto FooClass y devuelve undefined.

    Una forma de solucionar esto es hacer que FooClass implemente tanto Foo como Bar, incluso si realmente no utiliza la propiedad myVar2 de Bar. Otra posibilidad es agregar un guardia de tipo a la rama case "running" para verificar si el objeto es una instancia de Bar. Por ejemplo:

    function fbuToString(o: FooBarUnion ) {
        switch (o.kind) {
            case "pending": return `O está pendiente. ${o.myVar}`;
            case "running": 
                if ("myVar2" in o) {
                    return `O está en ejecución. ${o.myVar2}`;
                }
        }
    }
    

    Esto verifica si la propiedad myVar2 existe en o, lo que significaría que es una instancia de Bar, y devuelve la cadena esperada.

Comments are closed.