我有一个辅助函数,该函数接受和函数对象,并返回该对象的代理,该对象的功能由注入的第一个arg组成。
更好地显示在代码中:-
// example of object
export const selectors = {
selectA: (state:State) => state.a,
addToA : (state:State, num:number) => state.a + num
}
// ... in another file my helper fn
import {useSelector} from 'react-redux';
// PROBLEM IS HERE...
export const function bindSelector(obj){
return new Proxy(obj,{
get: (main, key, ctx) => {
const fn = main[key].bind(ctx);
// always inject store as first prop of fn
// we get store arg from useSelector higher order (its already properly typed)
return props => useSelector( store=> fn(store, props) )
}
})
}
export default bindSelector(selectors);
所以我使用Proxy,这样我就不必包括useSelector或将存储参数传递给每个选择器
此示例用法
import selectors from './a';
// now i can just
const a = selectors.selectA(); // give error param missing
const aAnd2 = selectors.addToA(2); // how to tell typescript that this first arg is in fact the 2nd arg :D !.
selecte require 1 param
的错误。答案 0 :(得分:1)
您可以使用一些映射和条件类型将原始对象映射到一个新对象,其中每个函数都具有一个较少的参数:
import { useSelector } from 'react-redux';
type State = {
a: number
}
// example of object
export const selectors = {
selectA: (state: State) => state.a,
addToA: (state: State, num: number) => state.a + num
}
type CurriedFunctionObject<T> = {
[P in keyof T]: T[P] extends (s: State, ...p: infer P) => infer R ? (...p: P) => R : never
}
export function bindSelector<T extends Record<string, (...a: any) => any>>(obj: T): CurriedFunctionObject<T> {
return new Proxy(obj, {
get: (main, key, ctx) => {
const fn = main[key as keyof T].bind(ctx);
// always inject store as first prop of fn
// we get store arg from useSelector higher order (its already properly typed)
return (args: any[]) => useSelector(store => fn(store, ...args))
}
}) as any as CurriedFunctionObject<T>
}
const cSelectors = bindSelector(selectors);
const a = cSelectors.selectA(); // give error param missing
const aAnd2 = cSelectors.addToA(2)
您可以将State
替换为条件类型中的任何一种,以使该类型适用于任何状态。