Мы можем использовать сопоставленный тип и условный тип ReturnValue
, чтобы получить желаемый эффект.Однако есть некоторая загвоздка в том, как мы можем вывести типы для параметров функции.Если мы попытаемся сделать это за один вызов функции, параметры будут набраны как any
.
Так, например, это не будет работать должным образом:
function switchExp2<T extends { type: string }, R extends { [P in (T["type"]]: (v: Extract<T, { type: P }>) => any }>(u: T, o: R): ReturnType<R[keyof R]> {
return null as any;
}
let result2 = switchExp2(union, {
one: u => u.numeric, // u is implictly tyed as any
two: u => u.text // u is implictly tyed as any
});
Компилятор пытается вывести T
из всех возможных сайтов и просто сдается вместо того, чтобы прийти к выводу.Простое решение состоит в том, чтобы сначала исправить T
, а затем выполнить второй вызов для отображаемого объекта:
function switchExp<T extends { type: string }>(u: T) {
return function <R extends { [P in T["type"]]: (v: Extract<T, { type: P }>) => any }>(o: R): ReturnType<R[keyof R]> {
return null as any; // replace with reasonable implementation
}
}
let result: number | string = switchExp(union)({
one: u => u.numeric, //u is of type One
two: u => u.text // u is of type Two
});