2021年3月28日星期日

Typing reducer payload as an object type or array of such

I'm using useReducer to maintain state for an array of object types and I have a few action types. The interfaces looks like:

interface MyObject {    id: string;    foo: string;    bar: string;  }    interface Action {    type: 'add' | 'remove' | 'update';    payload?: Partial<MyObject>;  }  

The reducer function:

const reducer = (current: MyObject[], action: Action): MyObject[] => {    switch (action.type) {      case 'add':        return [...current, createBaseMyObject()];      case 'remove':        return current.filter((item) => item.id !== action.payload?.id);      case 'update':        return current.map((item) => {          if (item.id === action.payload?.id) {            return { ...item, ...action.payload };          }          return item;        });        default:        return current;    }  };  

That works ok but I also need to conditionally pass an array of MyObject as the payload to update in bulk. Tried changing types and function to this:

interface ReducerAction {    type: 'add' | 'remove' | 'update';    payload?: Partial<MyObject> | MyObject[];  }    const reducer = (current: MyObject[], action: Action): MyObject[] => {    switch (action.type) {      case 'add':        return [...current, createBaseMyObject()];      case 'remove':        // Property 'id' does not exist on type 'MyObject[]'        return current.filter((item) => item.id !== action.payload?.id);      case 'update':        // With proper typing maybe this should be dedicated case        if (Array.isArray(action.payload)) {          return action.payload;        }          return current.map((item) => {          // Property 'id' does not exist on type 'MyObject[]'          if (item.id === action.payload?.id) {            return { ...item, ...action.payload };          }          return item;        });        default:        return current;    }  };  

I'm trying to avoid assertion or extra runtime checks just to satisfy TS. If creating a dedicated case makes it easier that's fine. I'd just want to type it best as possible and ideally keep it simple. Thoughts?

https://stackoverflow.com/questions/66847307/typing-reducer-payload-as-an-object-type-or-array-of-such March 29, 2021 at 08:04AM

没有评论:

发表评论