Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function lacks ending return statement and return type does not include 'undefined'

Function lacks ending return statement and return type does not include 'undefined'.

In the following async await function I had return type of Promise: <any> but I wanted to correct that so I did the following:

export const getMarkets = async (): Promise<IGetMarketsRes> => {
  try {
    const nomicsUSD = prepHeaders('USD');
    const marketUSD = await nomicsUSD.get(exchangeMarketPrices);
    const nomicsUSDC = prepHeaders('USDC');
    const marketUSDC = await nomicsUSDC.get(exchangeMarketPrices);
    const nomicsUSDT = prepHeaders('USDT');
    const marketUSDT = await nomicsUSDT.get(exchangeMarketPrices);

    console.log('marketUSD', marketUSD);

    return {
      marketUSD: marketUSD.data,
      marketUSDC: marketUSDC.data,
      marketUSDT: marketUSDT.data
    }
  } catch (err) {
    console.error(err);
  }
}

However that creates the error above.

enter image description here

Where getMarkets is called:

export const fetchMarketPrices = (asset: string) => (dispatch: any) => {
  dispatch(actionGetMarketPrices);
  return getMarkets().then((res) => {
    const { marketUSD, marketUSDC, marketUSDT } = res;
    const combinedExchanges = marketUSD.concat(marketUSDC).concat(marketUSDT);
    const exchangesForAsset = combinedExchanges.filter((marketAsset: IMarketAsset) =>
      marketAsset.base === asset);
    return dispatch(actionSetMarketPrices(exchangesForAsset));
  });
}

What is/are the proper Types for that Promise<> syntax?


I also tried this which I expected to be the correct way, but got a missing return for Promise, but this is an async await function which is why the return is in the try statement:

export const getMarkets = async (): Promise<IGetMarketsRes> => {

enter image description here

like image 273
Leon Gaban Avatar asked Feb 21 '19 16:02

Leon Gaban


3 Answers

The best solution would be to throw an error on the catch, instead of undefining the return type. The undefined type removes the whole point of using TypeScript otherwise.

Try this:

export const getMarkets = async (): Promise<IGetMarketsRes> => {
  try {
     // Your code :)
  } catch (err) {
    // Throw error
    throw(err)
  }
}
like image 164
Nojze Avatar answered Oct 13 '22 16:10

Nojze


Solution to keep the try catch

export const getMarkets = async (): Promise<IGetMarketsRes | undefined> => {
  try {
    const nomicsUSD = prepHeaders('111');
    const marketUSD = await nomicsUSD.get(exchangeMarketPrices);
    const nomicsUSDC = prepHeaders('222');
    const marketUSDC = await nomicsUSDC.get(exchangeMarketPrices);
    const nomicsUSDT = prepHeaders('333');
    const marketUSDT = await nomicsUSDT.get(exchangeMarketPrices);

    const { data: dataUSD } = marketUSD;
    const { data: dataUSDC } = marketUSDC;
    const { data: dataUSDT } = marketUSDT;

    if (R.isEmpty(dataUSD) || R.isEmpty(dataUSDC) || R.isEmpty(dataUSDT)) {
      console.error('Market data unavailable');
    }

    return {
      marketUSD: marketUSD.data,
      marketUSDC: marketUSDC.data,
      marketUSDT: marketUSDT.data
    }
  } catch (error) {
    console.error(error);
  }
}

A Much better DRY example

https://codereview.stackexchange.com/questions/213909/get-an-array-of-currency-exchange-prices-based-on-asset

export const fetchMarket = async (currency: string): Promise<any> => {
  try {
    const request = prepHeaders(currency);
    const response =  await request.get(EXCHANGE_MARKET_PRICES);
    if (!response) {
      throw new Error('USD Markets unavailable.');
    }
    return response.data;
  }
  catch(err) {
    console.error(err);
  }
}

// GET Market prices
// http://docs.nomics.com/#operation/getMarkets
export const getMarkets = async (): Promise<IGetMarketsRes | undefined> => {
  try {
    const markets: IMarketRes = {};

    for (let currency of BASE_CURRENCIES) {
      const key = 'market' + currency;
      markets[key] = await fetchMarket(currency);
    }

    return {
      marketUSD: markets['marketUSD'],
      marketUSDC: markets['marketUSDC'],
      marketUSDT: markets['marketUSDT'],
    }
  } catch (error) {
    console.error(error);
  }
}

And the call from the actions file:

// Fetch USD, USDC & USDT markets to filter out Exchange List.
export const fetchMarketPrices = (asset: string) => (dispatch: any) => {
  dispatch(actionGetMarketPrices);
  return getMarkets().then((res) => {
    if (res) {
      const exchangesForAsset = combineExchangeData(asset, res);
      return dispatch(actionSetMarketPrices(exchangesForAsset));
    }
  });
}
like image 28
Leon Gaban Avatar answered Oct 13 '22 16:10

Leon Gaban


In case of an error, your code implicitly returns undefined because you catch the error without rethrowing it.

I guess that your tsconfig.json file has noImplicitReturns set to true. If you change it to false, the compiler error will not show up anymore. However, I suggest to keep noImplicitReturns set to true and to re-throw the error in your catch clause.

You can also return a default IGetMarketsRes in the catch block if it works with your application logic. I made a video which shows you the different possibilities to handle error TS2366: https://www.youtube.com/watch?v=8N_P-l5Kukk&t=363s

like image 27
Benny Neugebauer Avatar answered Oct 13 '22 17:10

Benny Neugebauer