add actions

This commit is contained in:
Yanick Champoux 2022-08-25 14:19:45 -04:00
parent d20f50e156
commit 64782096df
2 changed files with 65 additions and 0 deletions

14
src/actions.test.ts Normal file
View File

@ -0,0 +1,14 @@
import { test, expect } from 'vitest';
import { action } from './actions.js';
test('basic action', () => {
const foo = action('foo', (thing: string) => ({ thing }));
expect(foo('bar')).toEqual({
type: 'foo',
payload: {
thing: 'bar',
},
});
});

51
src/actions.ts Normal file
View File

@ -0,0 +1,51 @@
export type Action<T extends string = string, TPayload = any> = {
type: T;
meta?: Record<string, unknown>;
payload?: TPayload;
};
export type ActionGenerator<
TType extends string = string,
TPayloadGen = (...args: any[]) => any,
> = {
type: TType;
} & (TPayloadGen extends (...args: any) => any
? ReturnType<TPayloadGen> extends void
? (...args: Parameters<TPayloadGen>) => {
type: TType;
}
: (...args: Parameters<TPayloadGen>) => {
type: TType;
payload: ReturnType<TPayloadGen>;
}
: (...args: any[]) => { type: TType; payload?: unknown });
export function action<
TType extends string,
TPayload extends (...args: any) => any,
>(
type: TType,
payloadFunction?: TPayload,
transformer?: Function,
): ActionGenerator<TType, TPayload> {
let generator: any = function (...payloadArg:any[]) {
const result: Action = { type };
if (payloadFunction) {
result.payload = payloadFunction(...payloadArg);
} else {
if (payloadArg[0] !== undefined) result.payload = payloadArg[0];
}
return result;
};
if (transformer) {
const orig = generator;
generator = (...args: any) => transformer(orig(...args), args);
}
generator.type = type;
return generator;
}