在调用 combineReducers 时隐式实例化的函数类型中声明的类型参数缺少类型注释

kmw*_*ter 5 javascript instantiation implicit flowtype redux

我现在在 Redux 中的 combineReducers 上收到以下错误。

缺少类型注释AA是在函数类型 [1] 中声明的类型参数,并在调用combineReducers[2] 时隐式实例化。

代码如下所示,但出现在我所有使用 combineReducers 的减速器中。

export default combineReducers({
  status: ((state: boolean = true, action: Action) => {
    switch (action.type) {
      case 'START_SESSION':
      case 'REFRESH_AUTH_SUCCEEDED':
      case 'SIGN_IN_FAILED':
      case 'SIGN_OUT':
        return false;
      default:
        return state;
    }
  }: Reducer<*>),
});
Run Code Online (Sandbox Code Playgroud)

我相信这是因为 Redux flow-types 中的这种类型定义


declare export function combineReducers<O: Object, A>(reducers: O): 
       CombinedReducer<$ObjMap<O, <S>(r: Reducer<S, any>) => S>, A>;

Run Code Online (Sandbox Code Playgroud)

我相信这与 Flow 的发布有关,版本 0.85.0 引入了一些与“隐式实例化”有关的东西。

我阅读了 Flow 自己的 Sam Goldman 在 Medium 上发表的这篇文章,这就是我得出这个结论的原因。 https://medium.com/flow-type/asking-for-required-annotations-64d4f9c1edf8

通过执行以下操作,我能够消除错误,这是我尝试实现类似文章中提到的解决方案“为函数调用提供显式类型参数”的尝试。

export default combineReducers<Object, Action>({
  status: ((state: boolean = true, action: Action) => {
    switch (action.type) {
      case 'START_SESSION':
      case 'REFRESH_AUTH_SUCCEEDED':
      case 'SIGN_IN_FAILED':
      case 'SIGN_OUT':
        return false;
      default:
        return state;
    }
  }: Reducer<*>),
});
Run Code Online (Sandbox Code Playgroud)

我这样做是因为我看到 Redux 文档中的函数定义是

combineReducers<O: Object, A>

Run Code Online (Sandbox Code Playgroud)

但是我不完全理解为什么会这样,或者不知道这实际上是正确的解决方案还是没有意义,我只是很幸运。我曾尝试在 Google 上搜索 IMPLICIT INSTANTIATIONS,但我什么也没找到。我准备好了这篇文章,但我仍然不知道调用的返回类型应该基于什么进行注释

combineReducers<O: Object, A>

Run Code Online (Sandbox Code Playgroud)

Ale*_*lex 3

长话短说

替换Object为您的对象,其中键是您的状态键,值是您的减速器定义:{status: Reducer<boolean, Action>}

所以你会得到:

combineReducers<{status: Reducer<boolean, Action>}, Action>(...)

长答案。

Reducer<S, any>- reducer 是一个纯函数,它接受当前状态和操作并返回新状态。就是这样,非常简单。这样它就可以在flow-typed中准确描述:

declare export type Reducer<S, A> = (state: S | void, action: A) => S

$ObjMap<O, <S>(r: Reducer<S, any>) => S>- 这更复杂,映射给定的对象O,调用每个成员(我们希望它们是函数)并返回类型。查看文档,这是非常强大的东西。

这部分:<S>(r: Reducer<S, any>) => S可能被称为extract function type。用人类的话来说,可以说是 -> reducer 可能返回任何类型,对吧?因此,让我们将reducer返回的状态放入generic中<S>,然后将返回的类型放入此generic中。我需要超过 1 天的时间来了解它是如何工作的,希望在你的情况下它会更快。:)

所以最后:combineReducer<S, A>- 给定状态S(这是对象,每个成员都是减速器)和操作A返回一个对象,该对象的成员是每次调用成员的结果类型S

所以,你的status减速函数 - 可以更好地描述为

Reducer<boolean, Action> //accepts boolean, Action args & return boolean
Run Code Online (Sandbox Code Playgroud)

我们可以将状态定义为:

type State = { status: Reducer<boolean, Action> };

然后,将状态传递给combineReducer:

export default combineReducers<State, Action>({
    status: ((state: boolean = true, action: Action) => {
        switch (action.type) {
        case 'START_SESSION':
        case 'REFRESH_AUTH_SUCCEEDED':
        case 'SIGN_IN_FAILED':
        case 'SIGN_OUT':
            return false;
        default:
            return state;
        }
    }),
});
Run Code Online (Sandbox Code Playgroud)

要检查输入是否正确,您可以导入您的减速器,并转换表达式

const checkState = reducer({status: true}, {type: 'START_SESSION'});
(checkState.status: number); // ERROR
(checkState.status: boolean); // CORRECT

Run Code Online (Sandbox Code Playgroud)

希望能帮助到你。