Как написать generic-функцию?

Начинаю изучать Typescript и самое большое затруднение вызывают дженерики. Есть простой код на JS, функция wrapper оборачивает другую функцию:

const innerFunc = (params) => {
    return params.p.toString();
};

const innerFunc2 = (params) => {
    return params.p;
};

const wrapper = (wrappedFunc) => {
    return (params) => {
        let { p } = params;

        p += 1;

        return wrappedFunc({ p });
    };
};

console.log(wrapper(innerFunc)({ p: 1 })); // выводит результат сложения двух чисел = 2
console.log(wrapper(innerFunc2)({ p: "1" })); // выводит результат объединения двух строк = 11

Теперь этот пример на TypeScript:

interface IBaseParams {
    p: number | string
}

interface IParams1 extends IBaseParams {
    p: number
}

interface IParams2 extends IBaseParams {
    p: string
}

type FuncType<T extends IBaseParams> = (params: T) => string;

const innerFunc: FuncType<IParams1> = (params) => {
    return params.p.toString();
};

const innerFunc2: FuncType<IParams2> = (params) => {
    return params.p;
};

const wrapper = (wrappedFunc) => {
    return (params) => {
        let { p } = params;

        p += 1;

        return wrappedFunc({ p });
    };
};

Не могу понять, как здесь описать функцию wrapper, чтобы она была дженериком? Буду благодарен за пояснения. Цель - разобраться, а не просто получить компилируемый код.


Ответы (1 шт):

Автор решения: qwabra
interface IBaseParams { p: number | string }

interface IParams1 extends IBaseParams { p: number }
interface IParams2 extends IBaseParams { p: string }

type FuncType<T extends IBaseParams> = (params: T) => T['p'];
declare const innerFunc_1: FuncType<IParams1>;
declare const innerFunc_2: FuncType<IParams2>;

type $wrappedFunc = FuncType<IParams1> | FuncType<IParams2>
declare const wrapper: <T extends $wrappedFunc>(wrappedFunc: T)
    => (...params: Parameters<T>)
        => ReturnType<T>

test: {
    const res = wrapper(innerFunc_1)({ p: 1 })
}
test: {
    const res = wrapper(innerFunc_2)({ p: "1" })
}

Цель - разобраться

  1. Читай.
  2. Пиши.
    • Пиши но сильно не зацикливайся
    • Пиши но не реализуй, описывай только логику, только declare.
  3. Спрашивай.
    • Оформляй здесь вопросы.
    • Cпрашивай в комментариях.
    • И главное не забывай метку .
  4. Делись. Делись своими знаниями. gl ;)
→ Ссылка