Using Redux Toolkit with TypeScript, I want to be able to add a timestamp
property to all payloads using a prepare callback on createAction()
and maintain good type definitions. Currently I do this with a lot of repeated code like:
const timestampAdder = (unpreparedPayload) => {
const prepared = { payload: unpreparedPayload };
if (!unpreparedPayload.timestamp) {
prepared.payload.timestamp = Date.now();
}
return prepared;
};
export const someActionCreator = createAction(
'slice_name/action_name',
(
prePayload: Omit<MyPayloadInterface, 'timestamp'>
): { payload: MyPayloadInterface; } => timestampAdder(prePayload)
);
export const someActionCreator2 = createAction(
'slice_name/action2_name',
(
prePayload: Omit<EntirelyDifferentInterface, 'timestamp'>
): { payload: EntirelyDifferentInterface; } => timestampAdder(prePayload)
);
// ...repeat the same structure for each action I want to add "timestamp" to...
If this was plain JS (or less strict TS) I could do something like:
export const jsActionCreator1 = createAction('js/action_name1', timestampAdder);
export const jsActionCreator2 = createAction('js/action_name2', timestampAdder);
But because the interfaces for the various action creators in TS are different, I end up writing a lot of boilerplate for each to maintain good types. I could do the same in TS:
export const myActionCreator = createAction('slice_name/action3_name', timestampAdder);
But then I lose the benefit of types, and I can invoke the action creator with any
argument:
myActionCreator(123);
myActionCreator('abc');
myActionCreator({ a: 1, b: 'c' });
Is there a good way to reduce boilerplate but maintain good types? Thanks!
Just do something like
const timestampAdder = <T>() => (unpreparedPayload: T) => {
const payload = Object.assign( { timestamp: Date.now() }, unpreparedPayload )
return { payload };
};
and use it like
export const actionCreator1 = createAction('js/action_name1', timestampAdder<{foo: string}>());
export const actionCreator2 = createAction('js/action_name2', timestampAdder<{bar: number}>());
Essentially, you have one method call wrapped around, just to "bind" the type there.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.