TypeScript 函数返回组合函数的映射对象
我正在尝试编写一个辅助函数,它接收一个函数对象并将其包装在另一个函数中;
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.
}
答案#1
试试这个:
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)
它还将强制 bindFn() 的第一个参数的形状必须是一个键为函数的对象(因为 T extends {[key: string]: Function})
答案#2
让我知道这是否是你想要的?我认为这是对的。
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}

