I am trying to create function builder for item creation reducers in redux toolkit slice, since most of them look practically same:
createSomething: (
state,
action: PayloadAction<Omit<typeof State["something_set"][number], "id">
) => {
const id = getId(state.something_set);
state.something_set.push({ ... action.payload, id });
}
So without types I would like to have something like this:
function createWithId(key) {
return (state, action) => {
const lst = state[key];
const id = getId(lst);
lst.push({ ...action.payload, id });
};
}
But I have trouble typing this function. I tried using KeysMatching<T, V>
type from answer to similiar question, but while it works when literally specifying type, it fails when used by type parameter like this:
// Reference: https://stackoverflow.com/questions/55150760/how-to-write-pickbyvalue-type
type PickByValue<T, V> = Pick<
T,
{ [K in keyof T]: T[K] extends V ? K : never }[keyof T]
>;
type KeysMatching<T, V> = {
[K in keyof T]: T[K] extends V ? K : never;
}[keyof T];
function createWithId<T extends { id: number }>(key: KeysMatching<State, T[]>) {
return (state: State, action: PayloadAction<Omit<T, "id">>) => {
const lst = state[key]; // ERROR! Type KeysMatching<State, T[]> cannot be used to index type State.
const id = getId(lst);
lst.push({ ...action.payload, id });
};
}
I cannot use nonparametric type, since there are differently typed lists in state. I also cannot simply use just keyof State
, since not all keys holds lists.
So how can I type this function or is there some better pattern for building similiar reducers?