Vyhledávání na webu

typescript - Odvozování typu podle parametru


V následujícím případě je možné správně odvodit typ result jako boolean?

interface ActionWithPayload<T extends string, K> { type: T, payload: K }

function ofType<T extends ActionWithPayload<string, any>>(...param: T["type"][]): T extends ActionWithPayload<typeof param[number], infer U> ? U : never {
    return null;
}

enum one {
    foo = "foo",
    bar = "bar"
}

type action = ActionWithPayload<one.foo, boolean> | ActionWithPayload<one.bar, string>;

var result = ofType<action>(one.foo); // type of result should be boolean

Odkaz na hřiště

Odpověď č. 1

Problém je v tom, že T["type"], když je T action, bude one.foo | one.bar bez ohledu na to, jaké parametry předáte. Potřebujete další obecný parametr, aby kompilátor odvodil doslovný typ pro člen výčtu, který předáte:

function ofType<T extends ActionWithPayload<string, any>, K extends one = one>(...param:K[]): T extends ActionWithPayload<K, infer U> ? U : never {
    return null as any;
}
var result = ofType<action, one.foo>(one.foo); // will be boolean

Nevýhodou je, že musíte explicitně určit literální typ one.foo, protože nemůžete určit jen jeden z typových parametrů. Jako alternativu můžete použít přístup se dvěma funkcemi, takže můžete určit typový parametr pro první funkci a nechat odvození typu pracovat pro druhou funkci:

function ofType<T extends ActionWithPayload<string, any>>() {
    return function <K extends one = one>(...param:K[]) : T extends ActionWithPayload<K, infer U> ? U : never{
         return null;
    }
}

var result = ofType<action>()(one.foo); // will be boolean