typescript 如何键入一个 Proxy 来 curry 其 props 并注入一个 prop
typescript how to type a Proxy that curry its props and inject a prop
我有一个辅助函数,它接受函数的对象和 return 该对象的代理,其函数由注入的第一个参数组成。
更好地显示在代码中:-
// 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);
所以我使用代理,这样我就不必包含 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 !.
问题
- 如果我将 bindSelector 键入 return 相同类型的 (obj),那么我会得到
selecte require 1 param
错误,因为 typescript 不知道我的代理已经提供了函数的第一个参数。
您可以使用一些映射类型和条件类型将原始对象映射到新对象,其中每个函数都少一个参数:
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
替换为任何类型,以使该类型适用于任何状态。
我有一个辅助函数,它接受函数的对象和 return 该对象的代理,其函数由注入的第一个参数组成。
更好地显示在代码中:-
// 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);
所以我使用代理,这样我就不必包含 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 !.
问题
- 如果我将 bindSelector 键入 return 相同类型的 (obj),那么我会得到
selecte require 1 param
错误,因为 typescript 不知道我的代理已经提供了函数的第一个参数。
您可以使用一些映射类型和条件类型将原始对象映射到新对象,其中每个函数都少一个参数:
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
替换为任何类型,以使该类型适用于任何状态。