将react dispatch箭头函数转换为tyescript

时间:2019-07-04 20:34:33

标签: javascript reactjs typescript ecmascript-6

在我的ES6 javascript react / redux代码中,我有类似的内容:

export const myFunction = params => dispatch => {
   ...code
   dispatch(...)
}

如何将其转换为打字稿?而不是使用Redux而是React useReducer

我失败的尝试是:

export const myFunction = (payload: any): void => dispatch:any => {
  ...code
  dispatch(...)
}

忘记了错误:

  • 参数“ dispatch”隐式具有“ any”类型。ts(7006)
  • 列表项类型'(dispatch:any)=> void'不能分配给'void'.ts(2322)

1 个答案:

答案 0 :(得分:1)

您要实现的目标是在Redux中使用,并促进bu Redux-thunk middlewareuseReducer挂钩中没有中间件。因此,这是不可能的。

但是您可以这样编写自己的中间件

import * as React from 'react';

interface FuncState {
    prop1: string;
    prop2: string;
}

interface FunctAction1 {
    type: 'SET_PROP1';  // Action type property has type of 'SET_PROP1'. This is not string, it is type 'SET_PROP1'. The only value type may have is 'SET_PROP1'.
    prop1: string;
}

interface FunctAction2 {
    type: 'SET_PROP2';
    prop2: string;
}

// Here we create union of actions to properly type Reducer
type KnownActions = FunctAction1 | FunctAction2;

const FuncInitState: FuncState = {
    prop1: '',
    prop2: ''
}

function isFunction(f: any): f is Function {
    return typeof f === "function";
}

function useThunkReducer<S, A>(reducer: React.Reducer<S, A>, initialState: React.ReducerState<React.Reducer<S, A>>):
[S, (action: A | ((dispatch: React.Dispatch<A>, state: S) => void)) => void] 
{

    const [state, dispatch] = React.useReducer(reducer, initialState);

    // Essentially this is middleware
    const thunkDispatch = (action: A
        | ((dispatch: React.Dispatch<A>, state: S) => void)): void => {
        if (isFunction(action)) { // This is type guard
            return action(dispatch, state);
        }

        return dispatch(action);
    };

    return [state, thunkDispatch];
}

const FuncReducer: React.Reducer<FuncState, KnownActions> = (state, action) => {
    switch (action.type) {
        case 'SET_PROP1':  
            // action will have type of FunctAction1 as action.type has value 'SET_PROP1'
            return { ...state, prop1: action.prop1 }
        case 'SET_PROP2':
            return { ...state, prop2: action.prop2 }
        default:
            throw new Error('FuncReducer do not have default');
    }
}

const myClickAction = (prop1: string) => (dispatch: React.Dispatch<KnownActions>) => {
    console.log(prop1);
    dispatch({ type: 'SET_PROP1', prop1: "some value" });
}

const FuncCmp: React.FunctionComponent = () => {
    const [state, dispatch] = useThunkReducer(FuncReducer, FuncInitState);
    return <div>
        FuncCmp
        <button onClick={(e) => dispatch(myClickAction("some value"))}>Set prop1</button>
        <button onClick={(e) => dispatch({ type: 'SET_PROP2', prop2: "another value" })}>Set prop2</button>
        <div>Prop1: {state.prop1}</div>
        <div>Prop2: {state.prop2}</div>
        </div>;
}

为了清楚起见,我在代码中添加了注释。

工作示例为here