typescript如何键入代理其道具并注入道具的代理

问题描述 投票:0回答:1

我有一个辅助函数,该函数接受和函数对象,并返回该对象的代理,该对象的功能由注入的第一个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);

所以我使用代理,这样我就不必包括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 !.

问题

  1. 如果我键入bindSelector以返回相同类型的(obj),那么我会得到selecte require 1 param错误,因为打字稿不知道我的代理已经为函数提供了第一个参数。
typescript generics closures currying
1个回答
0
投票

您可以使用一些映射和条件类型将原始对象映射到一个新对象,其中每个函数都具有一个较少的参数:


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)

Play

您可以用条件类型中的任何替换State,以使该类型适用于任何状态。

© www.soinside.com 2019 - 2024. All rights reserved.