Typescript how to return 2 different types defined by a generic type

407 Views Asked by At

I would like to make an abstract method that returns 2 different types.

It seems with my implementation typescript is expecting an intersection type of the 2 types, however I would like to have a union type of the 2 types: either one or the other.

This is my implementation:

export type ResponseByCategory = {
    cat_a: string,
    cat_b: number
}

export enum Category {
    cat_a = 'cat_a',
    cat_b = 'cat_b'
} 

export type Response<C extends Category> = {
    [c in Category]: ResponseByCategory[c]
}[C]

export function method<C extends Category>():Response<C>{
    const rand = Math.floor(Math.random()*2);
    switch(rand){
        case 0:{
            const a:Response<Category.cat_a> = 'A';
            return a;
            // ^
            // | Type 'string' is not assignable to type 'never'
        }    
        default:{
            const b:Response<Category.cat_b> = 1;
            return b;
            // ^
            // | Type 'number' is not assignable to type 'never'
        }    
    }
}

export const a = method<Category.cat_a>(); // Typescript knows a is a string
export const b = method<Category.cat_b>(); // Typescript knows b is a number

With this approach I got the errors when trying to return one or the other type. Typescript is expecting a type never to be returned, that is the intersection of string and number.

Is there a way for Typescript to infer the type I want to return, either one or the other according with the generic type defined in the method?

Of course, this is an oversimplified version of my application. I cannot return a simple union type and I must have some sort of abstraction that can handle lots of different categories.

Playground link

0

There are 0 best solutions below