从createSelector工厂推断返回类型

时间:2019-12-31 01:50:01

标签: typescript redux reselect

我正在尝试将reselect集成到某些Redux连接的组件中。根据用于重新选择(https://github.com/reduxjs/reselect#sharing-selectors-with-props-across-multiple-component-instances)的文档,在处理传入的道具时,为了确保正确记住选择器,您基本上为createSelector创建了一个工厂函数,因此每个调用{{1}的组件}拥有自己的选择器以及自己的记忆状态。这很有意义,我可以在TypeScript中使用它:

connect()

interface UploadProfileOwnProps { someValue: string; } const getUploadProfile = (state: AppState, props: UploadProfileOwnProps): UploadProfileState => state.uploadProfile; const getCustomer = (state: AppState, props: UploadProfileOwnProps): CustomerState => state.customer; const uploadProfileSelectorFactory = () => createSelector(getCustomer, getUploadProfile, (customerState, profile)=>({ customerId: customerState.customerId, ...profile })); type uploadProfileSelectorProps = ReturnType<ReturnType<typeof uploadProfileSelectorFactory>>; const connectUploadProfile = connect(()=>{ const selector = uploadProfileSelectorFactory(); const mapStateToProps = (state: AppState, props: UploadProfileOwnProps): uploadProfileSelectorProps =>{ return selector(state, props); }; return mapStateToProps; }, UploadProfileActions); 只是一个占位符,在这种情况下,状态完全不依赖于它,但在其他情况下,状态可能完全不依赖于它。双重OwnProps构造使我有些烦恼,但可以完成工作。现在,实际的问题:

ReturnType<ReturnType<>>缺少显式的返回类型。在这种情况下,我已经定罪了大骂我。如何说服TypeScript告诉它工厂函数的返回类型是uploadProfileSelectorFactory返回的类型?它确实可以正确推断返回类型,因此不会导致eslint怪异之外的任何问题。我看到一些选择:

  1. 只需告诉eslint忽略该行的返回类型要求即可。虽然最简单,但我不太喜欢。
  2. 明确定义组合器函数的类型,然后让工厂函数返回createSelector()的类型,在这种情况下,这将是一个相当混乱的CreateSelector,我必须记住如果我添加另一个选择器,则可以更改。
  3. 以某种方式说服TypeScript给我OutputParametricSelector<S, P, T, (res1: R1, res2: R2) => T>的返回类型,而无需实际调用它。尽管我还没有尝试过,但可以通过明确定义合并器函数的返回类型来完成此操作。这可能也可以摆脱createSelector()业务,但要让我保持合并器功能及其返回类型保持同步。
  4. ReturnType<ReturnType<>>或类似的东西扔进去,希望它没有这个问题。
  5. 调用一些可以解决整个问题的TypeScript黑魔法。

我希望将5和3进行某种组合,不过如果需要的话我会选择4。不幸的是,我发现的每个示例都只使用类型推断,而从未对此进行处理。

1 个答案:

答案 0 :(得分:0)

知道createSelector返回什么,因为最终它只是一个选择customerIdprofile的选择器。 reselect 创建的选择器必须有额外的属性,如 recomputationsresetRecomputations,但这些对于 react-redux 来说并不重要。我们只想知道选择器接受什么参数以及它返回什么。

这是您正在选择的内容:

type Selected = UploadProfileState & Pick<CustomerState, 'customerId'>

所以你可以用它代替 ReturnType<ReturnType<typeof uploadProfileSelectorFactory>>

uploadProfileSelectorFactory 的返回类型为:

(state: AppState, props: UploadProfileOwnProps) => Selected;

但这是冗长的,我们在多个地方都有这两个相同的参数,所以如果你愿意,你可以定义一个辅助类型:

type UploadProfileSelector<Return> = (state: AppState, props: UploadProfileOwnProps) => Return;

或更概括:

type ComponentSelector<Props, Return> = (state: AppState, props: Props) => Return;
type UploadProfileSelector<Return> = ComponentSelector<UploadProfileOwnProps, Return>;

您可以将其用作返回类型:

const uploadProfileSelectorFactory = (): UploadProfileSelector<Selected> =>