Why Types Help in React

A component's props are its public interface, and JSX gives no help in honoring it. Nothing in <PriceTag amount={1999} /> says whether the prop is called amount, whether it wants dollars or cents, or whether it is required. In JavaScript you find out by reading the component — and find out you read it wrong when the page renders $NaN.

A component and three calls that get it wrongCSS
interface PriceTagProps {
  amountCents: number;
  currency: 'USD' | 'EUR';
}
export function PriceTag({ amountCents, currency }: PriceTagProps) {
  return <span>{currency === 'USD' ? '$' : '€'}{(amountCents / 100).toFixed(2)}</span>;
}
export const cart = (
  <>
    <PriceTag amountCents="1999" currency="USD" />
    <PriceTag amountCents={1999} currency="GBP" />
    <PriceTag amountCents={1999} />
  </>
);
Output
src/why.tsx(11,15): error TS2322: Type 'string' is not assignable to type 'number'.
src/why.tsx(12,34): error TS2322: Type '"GBP"' is not assignable to type '"EUR" | "USD"'.
src/why.tsx(13,6): error TS2741: Property 'currency' is missing in type
  '{ amountCents: number; }' but required in type 'PriceTagProps'.

Three classes of bug, three errors, none needing the app to run: a value of the wrong type (the classic "1999" / 100), a value outside the allowed set, and a missing required prop. Misspell the prop name and you get a fourth. The second repays a look — 'USD' | 'EUR' is a union of literal types, so the compiler knows which strings are legal and your editor offers both. Rename amountCents and it lists every caller.

Types are erased before the code runs, so they describe your source and nothing else; two boundaries lie outside their reach.

Types cover the component tree; the network boundary must be checked at runtime
Types cover the component tree; the network boundary must be checked at runtime

await res.json() is typed any, so const user: User = await res.json() is a claim, not a check: a server that renames a field breaks the app as it would without TypeScript. Validate at the boundary with a schema library such as Zod 44,027 (github.com/colinhacks/zod (https://github.com/colinhacks/zod 44,027 )): UserSchema.parse(await res.json()) throws on bad data and returns a value typed from the schema — one declaration serving as both.