Добавление свойств в созданный Redux Store в Typescript
У меня проблемы с добавлением свойства при создании нового Redux Store в Typescript:
const bindMiddleware = middleware => {
if (process.env.NODE_ENV !== 'production') {
const { composeWithDevTools } = require('redux-devtools-extension')
return composeWithDevTools(applyMiddleware(...middleware))
}
return applyMiddleware(...middleware)
}
function configureStore (initialState = exampleInitialState) {
const sagaMiddleware = createSagaMiddleware()
const store = createStore(
rootReducer,
initialState,
bindMiddleware([sagaMiddleware])
)
store.sagaTask = sagaMiddleware.run(rootSaga)
return store
}
export default configureStore
со следующим сообщением об ошибке:
27:9 Property 'sagaTask' does not exist on type 'Store<{ error: any; count: number; lastUpdate: number; light: boolean; placeholderData: any; } | { lastUpdate: any; light: boolean; count: number; error: boolean; placeholderData: any; }, any>'.
25 | )
26 |
> 27 | store.sagaTask = sagaMiddleware.run(rootSaga)
| ^
28 |
29 | return store
30 | }
Какие-либо предложения?
2 ответа
@types/
| - redux.d.ts
src/
| ...
| ... store.ts
в redux.d.ts
import * as Redux from "redux"
declare module "redux" {
export interface Store {
sagaTask: ... // provide the types for `store.sagaTask` here
}
}
в store.ts
const store = createStore(...)
store.sagaTask = ...
это называется объединением объявлений / дополнением модуля.
Вам также необходимо настроить tsconfig.json
читать типы из этого @types
реж. Добавлять "typeRoots": [ "./@types", "./node_modules/@types" ]
к этому файлу (примечание: это относительно вашего baseDir
так что измените соответственно.
Также обратите внимание, что вы создаете контракт между вашими типами и кодом, который вы пишете. Если вам не удалось правильно настроить промежуточное ПО, sagaTask
будет Required
в типах, но undefined
в действительности.
Я не использовал Saga, поэтому я не уверен насчет лучших практик или возможных последствий этого подхода, но проблема в том, что тип Store не имеет sagaTask, поэтому TypeScript не допустит этого. Самый простой способ решить эту проблему - расширить Store и добавить поле sagaTask, а затем скопировать старое хранилище в новый объект расширенного типа.
Недостатком этого является то, что вы можете легко столкнуться с ситуацией, когда функция ожидает объект с типом Store, поэтому она не примет этот новый объект.
Вы уверены, что это должно быть собственностью магазина, или вы можете просто запустить sagaMiddleware.run(rootSaga)?