Exploring the given interface:
interface TestState {
a: number;
b: string;
}
My goal is to create a generic type that enforces an object to:
- have the same keys as a specified interface (e.g. TestState)
- for each key, provide a value of a reducer function, with the state type in TestState.
For instance, an object following this pattern would appear like this:
const test: StateSlices<TestState> = {
a: (state: number, action: any) => state,
b: (state: string, action: any) => state,
};
I've attempted to define this type as shown below:
type StateSlices<T, K extends keyof T> = Record<
keyof T,
(state: T[K], action: any) => T[K]
>;
However, when I implement it like this:
const test: StateSlices<TestState, keyof TestState> = {
a: (state: number, action: any) => state,
b: (state: string, action: any) => state,
};
I encounter compilation errors related to typing conflicts between strings and numbers.
Type '(state: number, action: any) => number' is not assignable to type '(state: string | number, action: any) => string | number'.
Types of parameters 'state' and 'state' are incompatible.
I'm struggling to find the correct typing for this scenario, despite my efforts throughout the day. Ideally, I want to specify types for actions too, but given the issues with state typing, I've kept them as 'any'.
Any assistance on this matter would be highly valued.
EDIT
In addition, if I wish to link various state slices with specific actions, what approach could be most suitable?
For example:
const test: StateSlices<TestState, keyof TestState> = {
a: (state: number, action: "ADD" | "SUBTRACT") => state,
b: (state: string, action: "TO_LOWERCASE" | "TO_UPPERCASE") => state,
};
How can I associate slice 'a' of TestState with its corresponding actions, preventing error matches like this:
const test: StateSlices<TestState, keyof TestState> = {
a: (state: number, action: "TO_LOWERCASE" | "SUBTRACT") => state,
b: (state: string, action: "SUBTRACT" | "TO_UPPERCASE") => state,
};
Your input is greatly appreciated.