машинопись реагирует на избыточные действия, которые возвращают обещания - PullRequest
1 голос
/ 24 января 2020

в моем приложении реагирования я хотел бы скрыть реализацию избыточности от View logi c в своем собственном пакете «я называю это пакетом sdk», и я экспортирую множество хуков реакции из пакета sdk, чтобы его мог использовать любой клиент.

Вопрос вкратце.

const fetch = (params) => (dispatch) => api.get('/media', params); как я могу сказать машинописи пропустить thunk и иметь дело с возвращаемым значением функции thunk у меня есть объект Record, как его набрать пропустить среднюю функцию?

Контекст

код:

// hook.tsx
import * as actions from './actions'; // thunks
import * as selectors from './selectors'; // reselect.
import {useSelector, useDispatch} from 'react-redux';

export function useMedia(): [Selectors<typeof selectors>,Actions<typeof actions>] {
  // use ref to cache hook
  return  useRef([
    bindSelectors(selectors, useSelector),
    bindDispatch(actions, useDispatch()),
  ]).current;
}

теперь внутри моих представлений, когда мне нужно использовать этот фрагмент мультимедиа, который я использую.

import { useMedia } from '@sdk/media'

// ....
const [media, mediaActions] = useMedia();
// dispatch an action
mediaActions.fetch({limit:10}).then(console.log);
// select a slice using selector
const photos = media.photosOfAlbum(1);

мои взгляды не знают / не заботятся о том, как работает useMedia, так что я мог бы реально разделить обязанности внутри моей кодовой базы и упростить совместное использование кодов, тестирование и т. Д. c .., так как переключение реализации в любое время не затрагивает потребителей sdk ( Mobile / WebApp / даже nodejs приложения) никто не знает, что Redux использует питание SDK.

Проблема в том, что я не могу правильно набрать эти хуки .. (useMedia).

, поэтому мы имеем 2 вещи, чтобы ты здесь функция bindSelectors и функция bindDispatch.

bindSelectors

code

// @sdk/utils

function bindSelectors <T extends object>(selectors:T, useSelector): CurriedFunctionObject<T>{
  return new Proxy(selectors, {
    get: (main: T, key: keyof T, ctx: any) => {
      const fn = Reflect.get(main, key, ctx);

      // always inject store as first prop of fn
      // we get store arg from useSelector higher order (its already properly typed)
      return (props?: any) => useSelector(store => fn(store, props));
    },

}

, которую я использовал для базового взлома прямого вызова объекта селектора, если всегда сохраняется первый аргумент arg.

export type CurriedFunctionObject<T> = {
  [P in keyof T]: T[P] extends (
    s: import('../rootReducer').AppState,
    ...p: infer Ps
  ) => infer R
    ? (...p: Ps) => R
    : never;
};

теперь мои селекторы связаны и напечатаны, моя главная проблема заключается в том, как написать тип действий ..

bindDispatch

он работает во многом как bindSelectors. и я использую ActionCreatorsMapObject из 'redux-thunk', чтобы напечатать его

export function bindDispatch<T extends Record<string, any>>(
  obj: T,
  dispatch: Dispatch,
): ActionCreatorsMapObject<T> {
  return new Proxy(obj, {
    get: (main: T, key: keyof T, ctx) => {
      const fn = Reflect.get(main, key, ctx);

      return (...props: any[]) => dispatch(fn(...props));
    },
  });
}

Проблема с bindDispatch: -

, если я отправляю thunk, который возвращает обещание, он не введен правильно ..

пример выше код media.fetch({limit:10}).then///.then is will give error Свойство 'catch' не существует для типа '(отправка: любая, getState: любая, {}: {}) => любая'`

, так что в основном, так как действие извлечения выглядит следующим образом

const fetch = (params) => (dispatch) => api.get('/media', params);, поэтому оно ожидает функцию (dispatch), так как я могу сказать, что typcript пропускает thunk и обрабатывает возвращаемое значение функции thunk

1 Ответ

0 голосов
/ 25 января 2020

Вы можете определить что-то подобное в вашем global.d.ts (или поместить его в отдельный файл redux.d.ts для его разделения):

import { ThunkAction } from 'redux-thunk';
import { Action } from 'redux';

declare module 'redux' {
    export interface Dispatch<A extends Action = AnyAction> {
        <T extends ThunkAction<any, any, any, any>>(action: T): T extends ThunkAction<infer K, any, any, any> ? K : never;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...