Search code examples
typescriptserializationdiscriminated-union

How to use discriminated unions with classes


I'm trying to convert a discriminated union into a string. The discriminated union consists of two interfaces. If I call the function with a simple object that matches the one of the interfaces, I get the expected result. If I call the function with a class the implements the interface, I get undefined back. Can you explain this behavior to me? An is there any way around this?

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 is pending. ${o.myVar}`;
        case "running": return `O is running. ${o.myVar2}`;
    }
}

// prints undefined
console.log(fbuToString(new FooClass('test')));

// prints expected result
console.log(fbuToString({kind:'pending', myVar: 'test'}));

I'm running this file with ts-node filename.ts


Solution

  • You just declare class in kind you don't actually assign it

    class FooClass implements Foo {
        kind = 'pending' as const
        myVar: string
    
        constructor(text:string) {
            this.myVar = text;
        }
    }
    

    Playground Link