Is anyone familiar with creating a system similar to Redux/Redux-toolkit? What I'm attempting to do is implement a createSlice function like the one below:
interface Lobby {
players: string[];
}
const slice = createSlice<Lobby>({
addPlayer: (state, name: string) => ({ ...state, players: [...players, name ] }),
});
The expected output would be:
{
actions: { addPlayer: (name: string) => ({ type: 'addPlayer', payload: name }) }
reducer: (state: Lobby, action: { type: string, payload: any }) => Lobby
}
However, it seems that it's not possible to achieve this due to multiple generic arguments in createSlice
, and being unable to only partially apply state as a parameter.
The best solution so far is something along the lines of:
const createSlice = <S, T extends Record<string, (state: S, payload: any) => S>>(
actions: T
) => {
type ActionsType = {
[K in keyof T]: (
payload: Parameters<T[K]>[1]
) => { type: K; payload: Parameters<T[K]>[1] };
};
type ReducerType = (state: S, { type: string, payload: any }) => S;
return {
actions: ("implementation" as any) as ActionsType,
reducer: ("implementation" as any) as ReducerType,
};
};
This implementation can be used as shown below:
const slice = createSlice({
addPlayer: (state: Lobby, name: string) => ({ ...state, players: [...players, name ] }),
});
Although this works, there is an issue with the inferred type of parameter S
being considered as unknown
, resulting in a wrong reducer type. For example, the following scenario does not trigger a type error:
const actions = slice({
addPlayer: (state: Lobby, name: string) => 3, // This should cause a type error
});
At the moment, I am unsure how to proceed or rectify this issue..