repository | branch | endBranch |
---|---|---|
main |
walkthrough |
Let's take a look at this repository.
Things can get a little tricky when we don't have a default value to start out with. TypeScript can't help up out and make any assumptions on our behalf. Let's consider this code for a moment.
import { useEffect, useState } from 'react';
import Quotes from './quotes';
import InspirationalQuote from './quote';
import Loading from './loading';
export type Quote = {
id: number;
content: string;
source?: string;
};
export const fetchRandomQuote = async () => {
const response = await fetch(`/api/quotes/random`);
return response.json();
};
export const fetchQuotes = async (count: number) => {
const response = await fetch(`/api/quotes?limit=${count}`);
return response.json();
};
const Application = () => {
const [quote, setQuote] = useState();
useEffect(() => {
fetchRandomQuote().then(setQuote);
}, []);
if (!quote) return <Loading />;
return (
<main className="w-full max-w-2xl py-16 mx-auto">
{/* <InspirationalQuote content={quote.content} source={quote.source} /> */}
{/* <Quotes>
<div className="grid grid-cols-2 gap-4"></div>
</Quotes> */}
</main>
);
};
export default Application;
It doesn't even matter what the InspirationalQuote
is just yet or what properties it takes.
Look at this:
const [quote, useQuote] = useState();
The type is inferred as:
const quote: undefined;
Well, we're passing undefined
to useState
. If TypeScriptn was smart enough to assume that the number we passed to the useState
in our counter example meant that count
was a number, then the logic follows that quote
is of the type undefined.
Okay, so enough complaining—what are we going to do about it?
So, what do we do? We have a few options:
We could give it an empty value (e.g. { content: '', source: '' }
);
const [quote, setQuote] = useState({ content: '', source: '' });
This works, but it has two problems:
- We broke our loading functionality since
!quote
will never be a case. - It's not totally clear to TypeScript that
source
is optional.
We could also step in and help TypeScript out a bit by providing a type variable. If you hover over useState
you'll see something that starts with:
useState<{
content: string;
source: string;
}>;
Well, we can step in and provide that service for TypeScript.
const [quote, setQuote] = useState<Quote | undefined>();
Now, everything works as expected and we end on the walkthrough
branch. Let's try an exercise.