Определить тип возвращаемоего значения функции, в зависимости от переданного параметра
У меня есть тип:
type TaskType = "return professions";
И есть описанная функция в интерфейсе:
interface IInterfaceName
{
getReponse(message: string, task?: TaskType): string | string[];
}
Моя задача, чтобы функция возвращала не string | string[], а более известный тип. Для текущей задачи, если мы передаем в taks значение "return professions", функция должна вернуть string, если же я передам undefined (или же вызову функцию без передачи параметра), я хочу получить тип string.
Я слышал про infer, возможно оно окажется решением. Но я не пойму как это написать.
getResponse("test") // return type: string
getResponse("test", "return professions") // return type: string[]
Ответы (1 шт):
Из личного опыта: Всевозможные проверки в возвращаемом типе приводят к еще большей запутанности, хотя им так же можно найти применение.
В конкретном примере просто перегружается сигнатура, TS сам определит к чему больше подходят аргументы.
type TaskType = "return professions";
interface IInterfaceName
{
getReponse(message: string): string;
getReponse(message: string, task: TaskType): string[];
getReponse(message: string, task?: TaskType): string | string[];
}
UPD1: Еще примеры:
type TaskType = "a" | "b"
type TaskTypeObj = {
type: "a" | "b"
}
type TaskTypeReturns = {
a: string
b: string[]
}
interface IInterfaceName
{
getReponse<T extends (TaskType | undefined)>(message: string, task?: T): T extends undefined ? 123 : (T extends TaskType ? TaskTypeReturns[T] : never);
}
// Для извлечения типа определенного свойства
interface IInterfaceNameV2
{
getReponse<T extends TaskTypeObj>(message: string, task?: T): T extends {type: infer V} ? (V extends TaskType ? TaskTypeReturns[V] : never) : never;
}
function foo(name: IInterfaceName) {
const res1 = name.getReponse("xxx", 'a'); // string
const res2 = name.getReponse("xxx", 'b'); // string[]
// Обрати внимание, что без перегрузки мы получили не то что ожидаем - а вообще все типы
const res3 = name.getReponse("xxx"); // string | string[] | 123
}
function fooV2(name: IInterfaceNameV2) {
const res1 = name.getReponse("xxx", {type: 'a'}); // string
const res2 = name.getReponse("xxx", {type: 'b'}); // string[]
const res3 = name.getReponse("xxx"); // string | string[]
}
UPD2: Смотри еще