Добавление свойств в созданный 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)?

Другие вопросы по тегам