машинопись fn возвращает объект карты составных функций - PullRequest
2 голосов
/ 15 октября 2019

Я пытаюсь набрать вспомогательную функцию, которая получает объект функции и переносит его в другой fn;

const bindFn = (obj, wrapFn) => Object.entries(obj).reduce((carry, [key, fn])=>{
carry[key] = ( ...args ) => wrapFn(fn.apply(null, args))
return carry;
},{})


// example of usage

const n = bindFn( { sum: (x) => x+1 }, console.log);
n.sum(3); // this should console.log 4

Проблема в том, что я понятия не имею, как набрать bindFn для возврата правильного типа, который содержит объект с такими же ключами и возвращает типы предоставленного объекта. что-то вроде

interface BindFn = {
[name: keysof obj] : () => Returntype<obj[name]> :D !!! no clue.
}

Ответы [ 2 ]

0 голосов
/ 15 октября 2019

Попробуйте:

const bindFn = <T extends {[key: string]: Function}>(
  obj: T,
  wrapFn: Function
) => {
  return Object.entries(obj).reduce((carry, [key, fn]) => {
    carry[key] = (...args) => wrapFn(fn.apply(null, args));
    return carry;
  }, {}) as T;
};

const n = bindFn({ sum: (x: number) => x + 1 }, console.log);
n.sum(3);
n.sum('3'); // error: type string does not match number
n.foo(2);   // error: 'foo' does not exist on the first arg of bindFn
const z = bindFn('foo', console.log); // error: 'foo' is not the right shape

Таким образом, вы получите полезную проверку типов, потому что тип возвращаемого значения bindFn() всегда будет иметь ту же форму, что и его первый параметр. например, n.sum() будет иметь тип (x: number) => x + 1, потому что это то, что было передано bindFn() (потому что return ... as T)

VSCode hinting

Это будеттакже убедитесь, что форма первого параметра bindFn() должна быть объектом с клавишами, которые являются функциями (потому что T extends {[key: string]: Function})

More VSCode hinting

0 голосов
/ 15 октября 2019

Дайте мне знать, если вы этого хотите? думаю, что это правильно.

const bindFn = <A extends keyof any, B>(obj: Record<A, B>, wrapFn: (fn: (arg: B) => B) => any): typeof obj => Object.entries(obj).reduce((carry, [key, fn])=>{
    carry[key] = ( ...args: any[] ) => wrapFn(fn.apply(null, args))
    return carry;
}, {})

const obj = { name: () => "my name is", age: () => "my age is" };
const result = bindFn(obj, (arg) => {
    console.log("executed on");
    return arg;
})

или выполненная функция, версия

const bindFn = <A extends keyof any, B , C>(obj: Record<A, B>, wrapFn: (fn: (arg: B) => any) => C): Record<A, C> => Object.entries(obj).reduce((carry, [key, fn])=>{
    carry[key] = ( ...args: any[] ) => wrapFn(fn.apply(null, args))
    return carry;
}, {})

const obj = { name: () => "my name is", age: () => "my age is" };
const result = bindFn(obj, (arg) => {
    console.log("executed on");
    return 5;
}) // {name: number, age: number}
...