在我的react应用程序中,我想将View逻辑中的redux实现隐藏在其自己的包``我称之为sdk包''中,并且我从sdk包中导出react的Hooks集,以便任何客户端都可以使用它。
简短的问题。
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的工作方式,因此我可以在代码库中真正拆分职责,并简化代码共享,测试等工作。因为可以随时切换实施而不会影响sdk(移动/ webapp /甚至nodejs应用)的使用者人们知道,redux为sdk底层提供了动力。
问题是我不能正确键入这些挂钩..(useMedia)。
所以我们要在这里输入2件事。 bindSelectors函数和bindDispatch函数。
bindSelectors
码
// @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;
};
现在我的选择器已绑定并键入,我的主要问题是如何编写Actions类型。
bindDispatch
它像bindSelectors一样工作。我使用“ redux-thunk”中的ActionCreatorsMapObject进行输入
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'在类型'(dispatch:any,getState:any,{}:{})=> any'上不存在所以基本上因为提取动作看起来像这样
const fetch = (params) => (dispatch) => api.get('/media', params);
所以它期望一个函数(dispatch)
,所以我如何告诉打字稿跳过thunk并处理thunk函数的返回值 最佳答案
您可以在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;
}
}