javascript - Typescript (Type 'undefined' is not assignable to type) Why is my Array having a | undefined? - Sta

I have an array called binedMarkets which is either a bination of 5 or 3 different market arrays. All t

I have an array called binedMarkets which is either a bination of 5 or 3 different market arrays. All these arrays have the following interface IMarketAsset[]:

export interface IMarketAsset {
  exchange: string;
  base: string;
  quote: string;
  price_quote: string;
  timestamp: string;
}

Here is where the typescript error occurs:

const binedMarkets = asset !== 'BTC' && asset !== 'ETH' ?
  btcMarkets.concat(ethMarkets).concat(marketUSD).concat(marketUSDC).concat(marketUSDT) :
  marketUSD.concat(marketUSDC).concat(marketUSDT);

const filteredMarkets = binedMarkets.length > 0 ? filterByUSDbase(asset, binedMarkets) : [];

Argument of type '({ price_quote: string; exchange: string; base: string; quote: string; timestamp: string; } | undefined)[]' is not assignable to parameter of type 'IMarketAsset[]'. Type '{ price_quote: string; exchange: string; base: string; quote: string; timestamp: string; } | undefined' is not assignable to type 'IMarketAsset'. Type 'undefined' is not assignable to type 'IMarketAsset'.ts(2345)

const binedMarkets: ({
  price_quote: string;
  exchange: string;
  base: string;
  quote: string;
  timestamp: string;
} | undefined)[]

Why is binedMarkets an array of either an object of type IMarketAsset or undefined?

Full bineExchangeData Function

// Filter by BTC, ETH, USD, USDT or USDC prices
// If asset has BTC/ETH pairing, obtain exchange BTC/ETH price to calculate assets USD/USDT value
export const bineExchangeData =
  (asset: string, { marketBTC, marketETH, marketUSD, marketUSDT, marketUSDC }: IGetMarketsRes) => {
    const btcBasedExchanges = marketBTC.filter((market: IMarketAsset) => market.base === asset);
    const ethBasedExchanges = marketETH.filter((market: IMarketAsset) => market.base === asset);
    const btcUSDTprices = marketUSDT.filter((market: IMarketAsset) => market.base === 'BTC');
    const btcUSDprices = marketUSD.filter((market: IMarketAsset) => market.base === 'BTC');
    const ethUSDTprices = marketUSDT.filter((market: IMarketAsset) => market.base === 'ETH');
    const ethUSDprices = marketUSD.filter((market: IMarketAsset) => market.base === 'ETH');

    const btcPricedMarkets = filterByExchangeBase(btcBasedExchanges, btcUSDTprices, btcUSDprices);
    const ethPricedMarkets = filterByExchangeBase(ethBasedExchanges, ethUSDTprices, ethUSDprices);

    const btcMarkets = btcPricedMarkets.filter((market) => R.not(R.isNil(market)));
    const ethMarkets = ethPricedMarkets.filter((market) => R.not(R.isNil(market)));

    const binedMarkets = asset !== 'BTC' && asset !== 'ETH' ?
      btcMarkets.concat(ethMarkets).concat(marketUSD).concat(marketUSDC).concat(marketUSDT) :
      marketUSD.concat(marketUSDC).concat(marketUSDT);

    console.log('binedMarkets', binedMarkets);
    const filteredMarkets = binedMarkets.length > 0 ? filterByUSDbase(asset, binedMarkets) : [];
    console.log('filteredMarkets', filteredMarkets);

    if (R.isEmpty(filteredMarkets)) return [];

    return filteredMarkets.map((market: IMarketAsset) => {
      if (market) {
        return {
          ...market,
          price_quote: formatPrice(market.price_quote)
        }
      }
    });
  };

Util functions

Here are the 2 other util functions I use in the main function. Also I have narrowed down the problem to the btcMarkets and ethMarkets arrays. So looking at filterByExchangeBase.

import * as R from 'ramda'

import { USD_CURRENCIES } from '../shared/constants/api'
import { IMarketAsset } from '../shared/types'

const calculateBasePrice = (assetBtcPrice: string | number, btcPrice: string | number) => 
  (Number(assetBtcPrice) * Number(btcPrice)).toString();

export const filterByExchangeBase =
  (exchanges: IMarketAsset[], usdtExchanges: IMarketAsset[], usdExchanges: IMarketAsset[]) =>
    exchanges.map((exchange) => {
      let basePriced = usdtExchanges.filter((btcExchange) => btcExchange.exchange === exchange.exchange)[0];

      if (!basePriced) {
        basePriced = usdExchanges.filter((btcExchange) => btcExchange.exchange === exchange.exchange)[0];
      }

      if (basePriced) {
        const { price_quote: assetBtcPrice } = exchange;
        const { price_quote: btcPrice } = basePriced;

        return {
          ...exchange,
          price_quote: calculateBasePrice(assetBtcPrice, btcPrice)
        }
      }
    });

export const filterByUSDbase = (asset: string, binedMarkets: IMarketAsset[] | undefined) => {
  if (!binedMarkets) return [];
  return R.not(R.any(R.equals(asset))(USD_CURRENCIES))
    ? binedMarkets.filter((marketAsset: IMarketAsset) => {
      if (marketAsset && marketAsset.base) {
        return marketAsset.base === asset;
      }
    }) : [];
}

I have an array called binedMarkets which is either a bination of 5 or 3 different market arrays. All these arrays have the following interface IMarketAsset[]:

export interface IMarketAsset {
  exchange: string;
  base: string;
  quote: string;
  price_quote: string;
  timestamp: string;
}

Here is where the typescript error occurs:

const binedMarkets = asset !== 'BTC' && asset !== 'ETH' ?
  btcMarkets.concat(ethMarkets).concat(marketUSD).concat(marketUSDC).concat(marketUSDT) :
  marketUSD.concat(marketUSDC).concat(marketUSDT);

const filteredMarkets = binedMarkets.length > 0 ? filterByUSDbase(asset, binedMarkets) : [];

Argument of type '({ price_quote: string; exchange: string; base: string; quote: string; timestamp: string; } | undefined)[]' is not assignable to parameter of type 'IMarketAsset[]'. Type '{ price_quote: string; exchange: string; base: string; quote: string; timestamp: string; } | undefined' is not assignable to type 'IMarketAsset'. Type 'undefined' is not assignable to type 'IMarketAsset'.ts(2345)

const binedMarkets: ({
  price_quote: string;
  exchange: string;
  base: string;
  quote: string;
  timestamp: string;
} | undefined)[]

Why is binedMarkets an array of either an object of type IMarketAsset or undefined?

Full bineExchangeData Function

// Filter by BTC, ETH, USD, USDT or USDC prices
// If asset has BTC/ETH pairing, obtain exchange BTC/ETH price to calculate assets USD/USDT value
export const bineExchangeData =
  (asset: string, { marketBTC, marketETH, marketUSD, marketUSDT, marketUSDC }: IGetMarketsRes) => {
    const btcBasedExchanges = marketBTC.filter((market: IMarketAsset) => market.base === asset);
    const ethBasedExchanges = marketETH.filter((market: IMarketAsset) => market.base === asset);
    const btcUSDTprices = marketUSDT.filter((market: IMarketAsset) => market.base === 'BTC');
    const btcUSDprices = marketUSD.filter((market: IMarketAsset) => market.base === 'BTC');
    const ethUSDTprices = marketUSDT.filter((market: IMarketAsset) => market.base === 'ETH');
    const ethUSDprices = marketUSD.filter((market: IMarketAsset) => market.base === 'ETH');

    const btcPricedMarkets = filterByExchangeBase(btcBasedExchanges, btcUSDTprices, btcUSDprices);
    const ethPricedMarkets = filterByExchangeBase(ethBasedExchanges, ethUSDTprices, ethUSDprices);

    const btcMarkets = btcPricedMarkets.filter((market) => R.not(R.isNil(market)));
    const ethMarkets = ethPricedMarkets.filter((market) => R.not(R.isNil(market)));

    const binedMarkets = asset !== 'BTC' && asset !== 'ETH' ?
      btcMarkets.concat(ethMarkets).concat(marketUSD).concat(marketUSDC).concat(marketUSDT) :
      marketUSD.concat(marketUSDC).concat(marketUSDT);

    console.log('binedMarkets', binedMarkets);
    const filteredMarkets = binedMarkets.length > 0 ? filterByUSDbase(asset, binedMarkets) : [];
    console.log('filteredMarkets', filteredMarkets);

    if (R.isEmpty(filteredMarkets)) return [];

    return filteredMarkets.map((market: IMarketAsset) => {
      if (market) {
        return {
          ...market,
          price_quote: formatPrice(market.price_quote)
        }
      }
    });
  };

Util functions

Here are the 2 other util functions I use in the main function. Also I have narrowed down the problem to the btcMarkets and ethMarkets arrays. So looking at filterByExchangeBase.

import * as R from 'ramda'

import { USD_CURRENCIES } from '../shared/constants/api'
import { IMarketAsset } from '../shared/types'

const calculateBasePrice = (assetBtcPrice: string | number, btcPrice: string | number) => 
  (Number(assetBtcPrice) * Number(btcPrice)).toString();

export const filterByExchangeBase =
  (exchanges: IMarketAsset[], usdtExchanges: IMarketAsset[], usdExchanges: IMarketAsset[]) =>
    exchanges.map((exchange) => {
      let basePriced = usdtExchanges.filter((btcExchange) => btcExchange.exchange === exchange.exchange)[0];

      if (!basePriced) {
        basePriced = usdExchanges.filter((btcExchange) => btcExchange.exchange === exchange.exchange)[0];
      }

      if (basePriced) {
        const { price_quote: assetBtcPrice } = exchange;
        const { price_quote: btcPrice } = basePriced;

        return {
          ...exchange,
          price_quote: calculateBasePrice(assetBtcPrice, btcPrice)
        }
      }
    });

export const filterByUSDbase = (asset: string, binedMarkets: IMarketAsset[] | undefined) => {
  if (!binedMarkets) return [];
  return R.not(R.any(R.equals(asset))(USD_CURRENCIES))
    ? binedMarkets.filter((marketAsset: IMarketAsset) => {
      if (marketAsset && marketAsset.base) {
        return marketAsset.base === asset;
      }
    }) : [];
}
Share edited Mar 4, 2019 at 22:46 Leon Gaban asked Mar 4, 2019 at 22:33 Leon GabanLeon Gaban 39.1k122 gold badges349 silver badges550 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 1

Why is binedMarkets an array either and object of type IMarketAsset or undefined

Because any of the marketXXX arrays, is an array of IMarketAsset | undefined (instead of just IMarketAsset.

Try defining the type as an array for each option, instead of bining them:

const binedMarkets: {
    price_quote: string;
    exchange: string;
    base: string;
    quote: string;
    timestamp: string;
}[] | undefined[] = [];

The problem was that in my filterByExchangeBase util function, I used .map instead of .filter which would result in some undefined objects in that array. Switching to filter made sure that only existing items would make it into the array.

...

Update: By changing .map to .filter, the price_quote updates didn't take

Refactored the logic to make sure that btcMarkets and ethMarkets aren't used if they will be empty.

export const bineExchangeData =
  (asset: string, { marketBTC, marketETH, marketUSD, marketUSDT, marketUSDC }: IGetMarketsRes) => {
    const btcBasedExchanges = marketBTC.filter((market: IMarketAsset) => market.base === asset);
    const ethBasedExchanges = marketETH.filter((market: IMarketAsset) => market.base === asset);
    const btcUSDTprices = marketUSDT.filter((market: IMarketAsset) => market.base === 'BTC');
    const btcUSDprices = marketUSD.filter((market: IMarketAsset) => market.base === 'BTC');
    const ethUSDTprices = marketUSDT.filter((market: IMarketAsset) => market.base === 'ETH');
    const ethUSDprices = marketUSD.filter((market: IMarketAsset) => market.base === 'ETH');

    const btcPricedMarkets = notBTCorETH(asset) ? filterCryptoBase(btcBasedExchanges, btcUSDTprices, btcUSDprices) : [];
    const ethPricedMarkets = notBTCorETH(asset) ? filterCryptoBase(ethBasedExchanges, ethUSDTprices, ethUSDprices) : [];

    const btcMarkets = R.not(R.isEmpty(btcPricedMarkets)) ? btcPricedMarkets.filter((market: IMarketAsset) => R.not(R.isNil(market))) : [];
    const ethMarkets = R.not(R.isEmpty(ethPricedMarkets)) ? ethPricedMarkets.filter((market: IMarketAsset) => R.not(R.isNil(market))) : [];

    const binedMarkets = notBTCorETH(asset) ?
      btcMarkets.concat(ethMarkets).concat(marketUSD).concat(marketUSDC).concat(marketUSDT) :
      marketUSD.concat(marketUSDC).concat(marketUSDT);

    const filteredMarkets = filterByUSDbase(asset, binedMarkets);

    if (R.isEmpty(filteredMarkets)) return [];

    return filteredMarkets.map((market: IMarketAsset) => ({
      ...market,
      price_quote: formatPrice(market.price_quote)
    }));
  };

export const filterCryptoBase =
  (exchanges: IMarketAsset[] | any, usdtExchanges: IMarketAsset[], usdExchanges: IMarketAsset[]) => {
    return exchanges.map((exchange: IMarketAsset) => {
      let basePriced = usdtExchanges.filter((btcExchange) => btcExchange.exchange === exchange.exchange)[0];
      if (!basePriced) {
        basePriced = usdExchanges.filter((btcExchange) => btcExchange.exchange === exchange.exchange)[0];
      }

      if (exchange && basePriced && exchange.price_quote && basePriced.price_quote) {
        const { price_quote: assetBtcPrice } = exchange; // Asset price in BTC/ETH
        const { price_quote: usdPrice } = basePriced; // BTC/ETH price in USDT/USD
        const price_quote = calculateBasePrice(assetBtcPrice, usdPrice).toString();

        return {
          ...exchange,
          price_quote
        }
      }

      return null;
    });
  }

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744913389a4600685.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信