3 ms·
We were trying to add types to some of our code. And the types were getting ridiculously convoluted. And at that point it was like - maybe it's not the types th
by david422 4y ago
We were trying to add types to some of our code. And the types were getting ridiculously convoluted. And at that point it was like - maybe it's not the types that are the problem, maybe it's the interface that needs to be rewritten.
- emn13 4y agoThe OP's example of createActions smells like such a scenario. The way redux mashes up payloads and discriminators makes it hard to type correctly - as in objects are not simply composed, they're extended by adding properties, and for no immediately obvious reason (which might be because of my inexperience, granted). Had redux been developed in typescript from the start, I doubt it would have chosen this API. Then again, the current version is already in typescript, so perhaps that optimism is unwarranted; unfortunately my experience with it is years ago already.
- acemarke 4y agoThis particular use case is trying to strongly type the "Flux Standard Action" object shape. An object _may_ have a `payload` field for its data, _may_ have an `error` field that indicates this action represents an error, and _may_ have a `meta` field that provides additional descriptive information. This isn't part of the Redux core package, but it's a convention the community adopted shortly after Redux became popular. Redux Toolkit uses that as the standard structure for an action object. `createAction` defaults to just `{type, payload}`, but you can optionally provide a callback that adds the other `meta` and `error` fields. So yes, there's some additional complexity here because of the optional field contents, and this type is telling TS what the final type should look like based on which fields exist. Note that as an end user, you normally don't even call `createAction` yourself - it's automatically called as part of our `createSlice` API. What end users normally write is: export const counterSlice = createSlice({ name: 'counter', // `createSlice` will infer the state type from the `initialState` argument initialState, reducers: { increment: state => { state.value += 1 }, // Use the PayloadAction type to declare the contents of `action.payload` incrementByAmount: (state, action: PayloadAction<number>) => { // `action.payload` is now a `number` state.value += action.payload } } })
- srcreigh 4y agoCare to share more details about code smell patterns you noticed?