मैं दस्तावेज़ों के आधार पर एक रिप्लेस रिड्यूसर बनाता हूं लेकिन मैं' मैं टाइपस्क्रिप्ट और रेडक्स डॉक्स का उपयोग कर रहा हूं, इसका कोई उदाहरण नहीं है कि रिप्लेसर को ठीक से कैसे टाइप किया जाए, मैं एक कोशिश करता हूं लेकिन मेरी कोशिश useStore को ओवरराइड करती है, getState() के टाइपिंग को खोने वाले जेनरिक को अनदेखा करती है।

अवयव:

interface State {
  sim: number;
  nao: string;
}

function Experimente() {
  const store: InjectableStore = useStore<State>();
  const dispatch = useDispatch();

  store.getState(); // any
}

रेडक्स कॉन्फ़िगरेशन:

export const initStore = () => {
  const store: StoreCreator & WithAsync = createStore(
    createReducer(),
    composeEnhancers(
      applyMiddleware(thunk),
    ),
  );

  store.asyncReducers = {};

  store.injectPageReducer = (pageReducer) => {
    store.asyncReducers['page'] = pageReducer;
    store.replaceReducer(createReducer(store.asyncReducers));
  }

  return store;
}

function createReducer(asyncReducers?) {
  return combineReducers({
    ...staticReducers,
    ...asyncReducers
  })
}

परिभाषा टाइप करें:

export interface WithAsync {
  injectPageReducer?: (asyncReducer: Reducer) => void;
  asyncReducers?: IGenericObject<any>;
  replaceReducer?: typeof combineReducers;
}

export type InjectableStore = ReturnType<typeof useStore> & {
  injectPageReducer?: WithAsync['injectPageReducer']
}

मैं useStore टाइप रखते हुए replaceReducer रणनीति कैसे टाइप कर सकता हूं?

0
Alexandre Gomes 2 अक्टूबर 2020, 21:02

1 उत्तर

सबसे बढ़िया उत्तर

समस्या यह है कि आपके प्रकार InjectableStore को आपके स्टोर के बारे में कोई जानकारी नहीं मिल रही है। प्रकार ReturnType<typeof useStore> आपके विशिष्ट राज्य प्रकार को लागू नहीं करेगा क्योंकि useStore सामान्य है, लेकिन आपने इसे सामान्य तर्क प्रदान नहीं किया है, इसलिए यह इसके बजाय अपने स्वयं के डिफ़ॉल्ट का उपयोग करता है। useState का हस्ताक्षर है:

export function useStore<S = RootStateOrAny, A extends Action = AnyAction>(): Store<S, A>;

तो ReturnType<typeof useStore> Store<RootStateOrAny, AnyAction> बन जाता है।

Store, useStore, Reducer, आदि सभी जेनरिक हैं जो दो मानों पर निर्भर हैं: S जो कि राज्य का आकार है और A जो कि अनुमत कार्यों का प्रकार। A किसी भी मानक Action को अनुमति देने के लिए वैकल्पिक और डिफ़ॉल्ट हो सकता है। लेकिन अगर S प्रदान नहीं किया जाता है तो ये प्रकार आपके राज्य के बारे में कुछ नहीं जानते हैं।

मूल रूप से जब भी आप "रेडक्स" या "रिएक्ट-रेडक्स" से आयात किए गए प्रकार का उपयोग करते हैं तो आपको इसे S तर्क प्रदान करना होगा। आप अपने कस्टम प्रकारों जैसे InjectableStore को जेनेरिक बना सकते हैं जो एक स्टोर का आकार लेते हैं और उसे पास कर देते हैं, या आप उन्हें स्टोर को हमेशा अपने इंटरफ़ेस Store पर सेट करने के लिए कह सकते हैं। दूसरा तरीका आसान है तो चलिए इसे करते हैं।

आप ReturnType<typeof useStore<S, A>> का उपयोग नहीं कर सकते क्योंकि यह एक अमान्य सिंटैक्स है, लेकिन यह ठीक है क्योंकि हमने ऊपर फ़ंक्शन हस्ताक्षर में देखा कि रिटर्न प्रकार Store<S, A> है जो आपके मामले में Store<State> है।

प्रकार लागू करने की आवश्यकता और गहरी हो जाती है क्योंकि संपत्ति {injectPageReducer: (asyncReducer: Reducer) => void;} को पता होना चाहिए कि रेड्यूसर सिर्फ Reducer<any> (जो निहित है) नहीं है, बल्कि आपके राज्य (या आपके राज्य का हिस्सा) के लिए विशिष्ट है, इस मामले में )

जिस हिस्से में यह मुश्किल हो जाता है वह यह है कि ऐसा लगता है कि जब आप injectPageReducer फ़ंक्शन को कॉल करते हैं, जो बदले में store.replaceReducer को कॉल करता है, तो आप अपने राज्य का आकार बदल रहे हैं किसी ऑब्जेक्ट की कुंजी sim और nao के साथ किसी ऑब्जेक्ट के लिए sim, nao, और page< / कोड>। यह बुरा है और हम ऐसा नहीं करना चाहते। replaceReducer फंक्शन का सिग्नेचर वास्तव में हमें बताता है कि रिप्लेसमेंट रिड्यूसर को उसी स्टेट शेप S पर ऑपरेट करने की जरूरत है, जो ओरिजिनल है:

export interface Store<S = any, A extends Action = AnyAction> {
  /** ... */
  replaceReducer(nextReducer: Reducer<S, A>): void
  /** ... */
}

एक त्वरित समाधान page को State पर एक वैकल्पिक संपत्ति बनाना है, लेकिन यह लाइन में त्रुटियों का कारण बनता है। इसे आवश्यक बनाना और डिफ़ॉल्ट मान सेट करना बेहतर है।

मैं वास्तव में इस सेटअप को पसंद नहीं करता क्योंकि asyncReducers को Store की संपत्ति के रूप में सेट किया गया है, बजाय replaceReducer को पारित एक अस्थायी चर के रूप में, लेकिन मुझे लगता है कि यह सीधे redux डॉक्स उदाहरण तो मैं इसके साथ रोल करूंगा।

यहां आपका संशोधित कोड है।

मैंने WithAsync से छुटकारा पाया और इसे एक InjectableStore इंटरफ़ेस में बदल दिया, जिसमें Store प्लस (शायद) आपके दो ऐड-ऑन के सभी गुण हैं। चूंकि ऐड-ऑन वैकल्पिक हैं, इसलिए आपको कॉल करने से पहले यह जांचना होगा कि injectPageReducer मौजूद है या नहीं।

export type InjectableStore = Store<State, MyAction> & {
  injectPageReducer?: (pageReducer: Reducer<PageState, MyAction>) => void;
  asyncReducers?: Partial<ReducersMapObject<State, MyAction>>;
};
1
Linda Paiste 3 अक्टूबर 2020, 02:54