Добавление интерфейсов Typescript для глубоко вложенных объектов, возвращаемых API

Я новичок в Typescript и пытаюсь добавить типы в простое приложение. Я застрял на ошибке с глубоко вложенным объектом.

export default function AnimalAdoptionCosts() {
  const [currencyQuote, setCurrencyQuote] = useState({});
  const [userInput, setUserInput] = useState("");

    const fetchAdoptionRates = async (userInput: string) => {
    const response = await fetch(
      `http://localhost:5000/v1/adoptionRate?animal=${userInput}`
    );
    console.info(response);
    const body = await response.json();
    if (response.status !== 200) throw Error(body.message);
    setCurrencyQuote(body);
  };


  const handleSubmit = async (userInput: string) => {
    await fetchExchangeRates();
    const costToAdopt = currencyQuote?.data.quote.USD.price;
  };

  return (
    <>
      <form onSubmit = {() => handleSubmit(userInput)}>
        <label htmlFor = "animal">Enter an animal type</label>
        <input
          value = {userInput}
          id = "userinput"
          placeholder = "ex: Pomeranian"
          onChange = {(event) => setUserInput(event.target.value)}
        />
        <input type = "submit" value = "Submit" />
       {costToAdopt}
      </form>
    </>

Ошибка Typescript: [1] Property 'data' does not exist on type '{}'. TS2339 для этой строки: const costToAdopt = currencyQuote?.data.quote.USD.price;

Я понимаю, что это потому, что useState устанавливает значение по умолчанию как пустой объект, но это странно.

interface CurrencyQuote {
 data: {
    quote:  {
       USD:   {
         price: number
       }
    }
}

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

Кроме того, если вы гений TS, я бы хотел помочь выяснить, как вводить другую важную информацию в моей функции. Спасибо!

Первое, что я замечаю, это то, что нет причин для adoptionRates сохранять состояние, если только вы не используете его где-то еще?

Nick 21.12.2020 03:02

@Ник, хорошая мысль, я понял, упрощая свой код, я испортил имена некоторых переменных, теперь это currencyQuote, и после установки costToAdopt я хочу отобразить результат

stonerose036 21.12.2020 03:20

Даже с учетом этого изменения переменной, я думаю, вы правы в том, что ей не нужно сохранять состояние, я, вероятно, могу просто вернуть costToAdopt в fetchAdoptionRates fn

stonerose036 21.12.2020 03:22

При всем при этом я по-прежнему считаю, что в целом стоит написать полную типизацию для возвращаемого типа данных. Это дает вам все преимущества TS!

Nick 21.12.2020 03:23
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
Что такое компоненты React? Введение в компоненты | Типы компонентов
Что такое компоненты React? Введение в компоненты | Типы компонентов
Компонент - это независимый, многократно используемый фрагмент кода, который делит пользовательский интерфейс на более мелкие части. Например, если мы...
Введение в одну из самых важных концепций в React - функциональное программирование.
Введение в одну из самых важных концепций в React - функциональное программирование.
React разработан с использованием концепции функционального программирования, поэтому понимание функционального программирования важно для изучения...
Руководство спасателя React по созданию масштабируемых приложений
Руководство спасателя React по созданию масштабируемых приложений
А, React. Это одна из самых популярных библиотек JavaScript. Ее любят за гибкость, простоту использования и, будем честны, за то, что она позволяет...
0
4
570
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если вам нужно только costToAdopt, я бы рекомендовал просто сохранить это значение отдельно в вашем useState в виде числа. Это значительно упрощает набор текста, и вы можете избежать вложения.

const [costToAdopt, setCostToAdopt] = useState<number>(0);

// ...

const fetchAdoptionRates = async (userInput: string) => {
  const response = await fetch(
    `http://localhost:5000/v1/adoptionRate?animal=${userInput}`
  );
  console.info(response);
  const body = await response.json();
  if (response.status !== 200) throw Error(body.message);
  setCostToAdopt(body?.data?.quote?.USD?.price || 0);
};

// ...

Спасибо! Это очень помогло и упростило некоторые вещи. Я пошел дальше и добавил подобные типизации ко всем моим функциям useState. const [cryptos, setCryptos] = useState<Object>({}); const [conversionRateToUSD, setConversionRateToUSD] = useState<число>(0); const [userInput, setUserInput] = useState<string>(""); Есть ли что-то еще, что я должен сделать с точки зрения интерфейсов?

stonerose036 21.12.2020 03:42

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

Todd Skelton 21.12.2020 03:53

Другие вопросы по теме