Reputation: 39018
For example I want to remove the dispatch: any
here:
export const fetchAllAssets = () => (dispatch: any) => {
dispatch(actionGetAllAssets);
return fetchAll([getPrices(), getAvailableSupply()]).then((responses) =>
dispatch(actionSetAllAssets(formatAssets(responses))));
}
There are 2 actions I dispatch above, actionsGetAllAssets
and actionsSetAllassets
.
Here are the interfaces and actionCreators for both:
// Interfaces
interface IActions {
GET_ALL_ASSETS: string;
SET_ALL_ASSETS: string;
GET_MARKET_PRICES: string;
SET_MARKET_PRICES: string;
ADD_COIN_PORTFOLIO: string;
ADD_COINS_PORTFOLIO: string;
UPDATE_COIN_PORTFOLIO: string;
REMOVE_COIN_PORTFOLIO: string;
}
interface IGetAllAssets {
type: IActions['GET_ALL_ASSETS'];
loading: boolean;
}
interface ISetAllAssets {
type: IActions['SET_ALL_ASSETS'];
assets: IAsset[];
loading: boolean;
}
// ACTION CREATORS
const actionGetAllAssets = () => ({
type: Actions.GET_ALL_ASSETS,
loading: true
});
const actionSetAllAssets = (data: any) => ({
type: Actions.SET_ALL_ASSETS,
assets: data,
loading: false
});
So then I tried the following:
export const fetchAllAssets = () => (dispatch: IGetAllAssets | ISetAllAssets) => {
console.log('fetchAllAssets', dispatch);
dispatch(actionGetAllAssets);
return fetchAll([getPrices(), getAvailableSupply()]).then((responses) =>
dispatch(actionSetAllAssets(formatAssets(responses))));
}
However it produces this Typescript error:
Cannot invoke an expression whose type lacks a call signature. Type 'IGetAllAssets | ISetAllAssets' has no compatible call signatures.ts(2349)
Thoughts? Or is there a different way to type a dispatch event?
Upvotes: 27
Views: 70312
Reputation: 419
Action is an interface with type: T
(usually a string), that accepts a generic:
export interface Action<T = any> {
type: T
}
here is an example:
type GetBannerList = GetAllBanner | Error | Loading;
type Loading = {
type: string;
};
type GetAllBanner = {
type: string;
payload: PaginatedResponse<Banner>;
};
type Error = {
type: string;
payload: Error;
};
export const getBannersList = (
typeRegistration?: BannerRegistrationType
) => async (dispatch: Dispatch<GetBannerList>) => {
try {
dispatch(increaseLoading());
const payload = await BannerApi.getBannersList(typeRegistration);
dispatch({
type: GET_ALL_BANNERS,
payload,
});
} catch (err) {
if (err instanceof Error) {
dispatch({
type: PARTNERSHIP_ERROR,
payload: err,
});
}
} finally {
dispatch(decreaseLoading());
}
};
Upvotes: 0
Reputation: 5622
The Redux typings have a generic Dispatch<A>
type you can use, where A
is the type of action.
export const fetchAllAssets = () => (dispatch: Dispatch<IGetAllAssets | ISetAllAssets>) => {
// ...
}
Upvotes: 21
Reputation: 39018
I got a bit further!
Dispatch is an event function, so got this to work:
interface IAllAssets {
type: IActions['GET_ALL_ASSETS'];
assets?: IAsset[];
loading: boolean;
}
// ACTIONS
// Fetch assets from Nomics API V1.
export const fetchAllAssets = () => (dispatch: (arg: IAllAssets) => (IAllAssets)) =>
{
dispatch(actionGetAllAssets());
return fetchAll([getPrices(), getAvailableSupply()]).then((responses) =>
dispatch(actionSetAllAssets(formatAssets(responses))));
}
However I'd still like to create a dispatch
type
, something like:
interface IAllAssetsDispatch {
dispatch: (arg: IAllAssets) => (IAllAssets)
}
export const fetchAllAssets = () => (dispatch: IAllAssetsDispatch) => {
But this produces the same lacks a call signature error.
Forgot about type
that's what I needed to use instead of interface
for functions:
type DispatchAllAssets = (arg: IAllAssets) => (IAllAssets);
type DispatchMarketPrices = (arg: ISetMarket) => (ISetMarket);
type DispatchAddCoin = (arg: ICoinPortfolio) => (ICoinPortfolio);
type DispatchAddCoins = (arg: ICoinsPortfolio) => (ICoinsPortfolio);
// ACTIONS
// Fetch assets from Nomics API V1.
export const fetchAllAssets = () => (dispatch: DispatchAllAssets) => {
dispatch(actionGetAllAssets());
return fetchAll([getPrices(), getAvailableSupply()]).then((responses) =>
dispatch(actionSetAllAssets(formatAssets(responses))));
}
// Fetch USD, USDC & USDT markets to filter out Exchange List.
export const fetchMarketPrices = (asset: string) => (dispatch: DispatchMarketPrices) => {
dispatch(actionGetMarketPrices);
return getMarkets().then((res) => {
if (res && res.marketUSD && res.marketUSDC && res.marketUSDT) {
const exchangesForAsset = combineExchangeData(asset, res);
return dispatch(actionSetMarketPrices(exchangesForAsset));
}
else {
return dispatch(actionSetMarketPrices([]));
}
});
}
Upvotes: 6