Typescript期望undefined作为参数

时间:2017-06-28 01:10:09

标签: typescript redux

打字稿:2.4.1

我试图创建一个辅助函数来生成redux动作创建器。

我得到了什么:

interface IAction<T extends string, P = undefined> {
    type: T;
    payload: P;
}

function createAction<T extends string>(type: T): () => IAction<T, undefined>;
function createAction<T extends string = '', U = undefined, V = {}>(type: T, actionCreator: (payload: U) => V): (payload: U) => IAction<T, V>;
function createAction<T extends string>(type: T, actionCreator?: (payload?: any) => any) {
    return (payload: any) => ({
        payload,
        type,
    });
}

enum ActionType {
    INCREMENT = 'COUNTER/INCREMENT',
    DECREMENT = 'COUNTER/DECREMENT',
    ASYNC_INCREMENT = 'COUNTER/ASYNC_INCREMENT',
}

const increment = createAction(ActionType.INCREMENT, () => ({ amount: 1 }));
const incrementBy = createAction(ActionType.INCREMENT, (amount: number) => amount);

在这个例子中,我希望increment是一个带0个参数的函数,而incrementBy则取1(a number)。

incrementBy按预期工作,但在调用increment()(没有参数)时,Typescript会抛出此错误:

[ts] Expected 1 arguments, but got 0;

尝试以与我致电incrementBy相同的方式拨打电话,例如increment(42),我收到此错误:

[ts] Argument of type '42' is not assignable to parameter of type 'undefined';

这有效:increment(undefined)

有没有办法解决这个问题?

1 个答案:

答案 0 :(得分:1)

你应该简单地创建另一个重载,它表示它将返回一个没有参数的函数,而不是一个以undefined为唯一参数的函数。

function createAction<T extends string>(type: T): () => IAction<T, undefined>;
function createAction<T extends string, V>(type: T, actionCreator: () => V): () => IAction<T, V>;
function createAction<T extends string, U, V>(type: T, actionCreator: (payload: U) => V): (payload: U) => IAction<T, V>;
function createAction<T extends string, U, V>(type: T, actionCreator?: (payload: U) => V): (payload: U) => IAction<T, V> {
    return (payload: any) => ({
        payload,
        type,
    });
}

但是,您的实现似乎对传递的函数没有任何作用。你可能想这样做:

function createAction<T extends string>(type: T): () => IAction<T, undefined>;
function createAction<T extends string, V>(type: T, actionCreator: () => V): () => IAction<T, V>;
function createAction<T extends string, U, V>(type: T, actionCreator: (payload: U) => V): (payload: U) => IAction<T, V>;
function createAction<T extends string, U, V>(type: T, actionCreator?: (payload: U) => V): (payload: U) => IAction<T, V> {
    if (actionCreator) {
        return (payload: U) => ({
            payload: actionCreator(payload),
            type,
        });
    } else {
        return () => ({
            payload: undefined,
            type
        });
    }
}