Props with TypeScript

Type Your Props for Free Editor Help

Props with TypeScript

TypeScript is how modern React apps describe what props a component takes. It's a one-time cost for big editor + safety wins.

4 min read Level 2/5 #react#typescript#props
What you'll learn
  • Type a function component's props
  • Use unions for variant props
  • Type `children` and event handlers

If you’re using TypeScript, you describe what props a component takes with a type. Hovering a component in your editor then shows the full prop API, and calling it wrong is a compile error.

If you’re using plain JavaScript, you can skip this lesson — nothing here is required to use React. It’s a quality-of-life add-on, not a React feature.

Typing the Props

type GreetingProps = {
  name: string;
  age?: number;        // optional
};

function Greeting({ name, age }: GreetingProps) {
  return (
    <p>
      Hello {name}{age !== undefined ? `, ${age}` : ""}!
    </p>
  );
}

That’s the whole pattern: a type (or interface) right above the component, applied with : TheType on the parameter.

Children Are Typed As ReactNode

import type { ReactNode } from "react";

type PanelProps = {
  title: string;
  children: ReactNode;
};

function Panel({ title, children }: PanelProps) {
  return (
    <section>
      <h2>{title}</h2>
      <div>{children}</div>
    </section>
  );
}

ReactNode covers strings, numbers, JSX, arrays, null, and undefined — basically anything renderable.

Variant Props

Use a string union for “one of N”:

type ButtonProps = {
  kind: "primary" | "secondary" | "danger";
  children: ReactNode;
  onClick?: () => void;
};

function Button({ kind, children, onClick }: ButtonProps) {
  return (
    <button className={`btn btn--${kind}`} onClick={onClick}>
      {children}
    </button>
  );
}

Now <Button kind="banana" /> is a compile error.

Event Handlers

For the common event types, React ships handler types:

import type { ChangeEvent, MouseEvent } from "react";

function Input({ onChange }: { onChange: (e: ChangeEvent<HTMLInputElement>) => void }) {
  return <input onChange={onChange} />;
}

function Btn({ onClick }: { onClick: (e: MouseEvent<HTMLButtonElement>) => void }) {
  return <button onClick={onClick}>OK</button>;
}

In practice you can often write (e) => … and let TypeScript infer the type from context.

The Older PropTypes Library

Before TypeScript was everywhere, the prop-types package gave runtime validation:

import PropTypes from "prop-types";

function Greeting({ name }) { return <p>Hello, {name}!</p>; }

Greeting.propTypes = {
  name: PropTypes.string.isRequired,
};

It still works but is rare in new code. TypeScript is the recommended way to type props in modern React.

Up Next

Components that take input — buttons, fields, anything clickable. Time for events.

Events →