redux - Typescript mengharapkan undefined untuk dilewatkan sebagai argumen
Typescript: 2.4.1
Saya sedang mencoba membuat fungsi pembantu untuk menghasilkan pembuat aksi redux.
Apa yang saya punya:
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);
Dalam contoh ini, saya mengharapkan increment menjadi fungsi yang tidak mengambil argumen sama sekali, dan incrementBy mengambil tepat 1 argumen (sebuah number).
incrementBy bekerja seperti yang diharapkan, tetapi Typescript menampilkan kesalahan ini saat memanggil increment() (tanpa argumen):
[ts] Expected 1 arguments, but got 0;
Mencoba memanggilnya dengan cara yang sama seperti saya memanggil incrementBy, misalnya increment(42), saya mendapatkan kesalahan ini:
[ts] Argument of type '42' is not assignable to parameter of type 'undefined';
Ini berhasil: increment(undefined).
Apakah ada cara untuk memperbaiki ini?
Jawaban #1
Anda sebaiknya cukup membuat overload lain yang menyatakan bahwa itu akan mengembalikan fungsi tanpa argumen, daripada fungsi yang mengambil undefined sebagai satu-satunya argumen.
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,
});
}
Namun, implementasi Anda tampaknya tidak melakukan apa pun dengan fungsi yang diteruskan. Anda kemungkinan ingin melakukan ini:
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
});
}
}
