I'm new to Typescript and trying to add types to a simple app. I'm stuck on an error with a deeply nested object.
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>
</>
The Typescript error is: [1] Property 'data' does not exist on type '{}'. TS2339
for this line: const costToAdopt = currencyQuote?.data.quote.USD.price;
I get that this is because useState sets the default as an empty object, but it feels weird to do
interface CurrencyQuote {
data: {
quote: {
USD: {
price: number
}
}
}
is this what I should be doing? I found this example playground to work off of, but then I would make 4 different interfaces, which seems overcomplicated.
Also if you're a TS whiz, I'd love help figuring out how to type out the other important info in my function. Thank you!
If you only need costToAdopt
, I'd recommend just storing that value alone in your useState
as a number. That makes the typing a lot easier and you can avoid all the nesting.
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);
};
// ...