为 API 返回的深层嵌套对象添加 Typescript 接口

Adding Typescript interfaces for deeply nested object returned by 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.log(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
       }
    }
}

这是我应该做的吗?我找到了这个example playground to work off of,但是我会制作 4 个不同的界面,这看起来太复杂了。

此外,如果您是 TS 高手,我很乐意帮助您弄清楚如何在我的函数中输入其他重要信息。谢谢!

如果您只需要 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.log(response);
  const body = await response.json();
  if (response.status !== 200) throw Error(body.message);
  setCostToAdopt(body?.data?.quote?.USD?.price || 0);
};

// ...