Home > Blockchain >  Typescript return type based on value of object property
Typescript return type based on value of object property

Time:06-05

I have the following code that is somewhat based on this answer to a similar question:

interface A {
    type: "a";
    data: string;
}

interface B {
    type: "b";
    data: string;
}

type Helper<T extends A | B> = 
    T["type"] extends A["type"] ? A : 
    T["type"] extends B["type"] ? B : 
    never;
    
const get = <T extends A | B>({ type }: Pick<T, "type">): Helper<T> => {

    return {
        type,
        data: type,
    } as Helper<T>;

};

const mySelected = get({ type: "a" });
console.log(mySelected);

my get function should return an object of type A if the first arguments type is a and one of type B if its first arguments type is "b".
In my code however mySelected has the type never.
If I change the function call to get<A>({ type: "a" }) I get the correct type of A, but I would like Typescript to figure this out on its own. Furthermore, if I change the function call to get<B>({ type: "a" }), Typescript notices that something is wrong and complains that Type '"a"' is not assignable to type '"b"'..

CodePudding user response:

Bases upon the previous answer you linked:

interface A {
    type: "a";
    data: string;
}

interface B {
    type: "b";
    data: string;
}

const get = <T extends Pick<A | B, 'type'>>({ type }: T ) => {
    return {
        type,
        data: type,
    } as    T extends Pick<A, 'type'> ? A :
            T extends Pick<B, 'type'> ? B :
            never
};

const mySelectedA = get({ type: "a" }); // const mySelectedA: A
const mySelectedB = get({ type: "b" }); // const mySelectedB: B
const mySelectedC = get({ type: "c" }); // const mySelectedC: never | Type '"c"' is not assignable to type '"a" | "b"'.(2322)

  • Related