I am using the useReducer React Hook like shown in this Video. I adapted it to my needs and it works. But because I am using Typescript, I am wondering if it is possible to define what combination can be put into the function. I have following code (very simplified):
interface actionType {
type: string,
payload: {
count?: number,
first?: number,
second?: number,
nameOfPerson?: string,
message?: string
}
}
const ACTIONS = {
ADD_ONE: 'addOne',
MULTIPLY: 'multiply',
ADD_TOGETHER: 'addTogether',
}
const theFuntion = (action: actionType) => {
const { type, payload } = action
switch (type) {
case ACTIONS.ADD_ONE: {
const result: number = payload.count + 1
return result;
};
case ACTIONS.MULTIPLY: {
const result: number = payload.first * payload.second
return result;
};
case ACTIONS.ADD_TOGETHER: {
const result: string = payload.nameOfPerson + payload.message
return result;
};
}
}
Following works:
theFuntion({ type: ACTIONS.ADD_ONE, payload: { count: 9 } }) // works
theFuntion({ type: ACTIONS.MULTIPLY, payload: { first: 3, second: 5 } }) // works
theFuntion({ type: ACTIONS.ADD_TOGETHER, payload: { nameOfPerson: 'Peter', message: 'Hello Wolrd!' } }) // works
These will and should not work, but does not show type error’s:
theFuntion({ type: ACTIONS.MULTIPLY, payload: { count: 9 } })
theFuntion({ type: ACTIONS.ADD_TOGETHER, payload: { first: 3, second: 5 } })
theFuntion({ type: ACTIONS.ADD_ONE, payload: { nameOfPerson: 'Peter', message: 'Hello Wolrd!' } })
So my question is if there is a way to define an interface or something else to show me if I make a combination error when coding, because my code is ‘original code’ is way more complex and if I continue to add even more ACTIONS than I currently have (not just 3 like in my example) it will get hard to keep things in order and not get surprised while testing with ‘undefined’.
Probably unimportant, but the function should be for the useReducer React Hook and would look something like this:
export const reducerFuntion = (state: stateType, action: typeForActionsType) => {
...
}
>Solution :
You’ll need a discriminated union for that !
type ActionType = 'AddOne' | 'Multiply' | 'AddTogether'
type AddOne = { type: 'AddOne', payload: { count: number } }
type Multiply = { type: 'Multiply', payload: { first: number, second: number } }
type AddTogether = { type: 'AddTogether', payload: { nameOfPerson: string, message: string } }
type Action = AddOne | Multiply | AddTogether;
const theFuntion = (action: Action) => {
switch (action.type) {
case "AddOne": {
const result: number = action.payload.count + 1
return result;
};
case "Multiply": {
const result: number = action.payload.first * action.payload.second
return result;
};
case "AddTogether": {
const result: string = action.payload.nameOfPerson + action.payload.message
return result;
};
}
}
theFuntion({ type: "AddOne", payload: { count: 9 } }) // works
theFuntion({ type: "Multiply", payload: { first: 3, second: 5 } }) // works
theFuntion({ type: "AddTogether", payload: { nameOfPerson: 'Peter', message: 'Hello Wolrd!' } }) // works
// These show an error
theFuntion({ type: "Multiply", payload: { count: 9 } })
theFuntion({ type: "AddTogether", payload: { first: 3, second: 5 } })
theFuntion({ type: "AddOne", payload: { nameOfPerson: 'Peter', message: 'Hello Wolrd!' } })