Component Props

`Astro.props` Plus a Typed `Props` Interface

Component Props

Props arrive at the component via `Astro.props`. Declare a `Props` interface in the frontmatter for type safety.

4 min read Level 1/5 #astro#props#typescript
What you'll learn
  • Pass and receive props
  • Type props with an `interface`
  • Default values and `...rest`

A component receives data from its parent through props. In an Astro file, props live on Astro.props. The typical pattern is to declare a TypeScript interface called Props at the top of the frontmatter, then destructure.

The Pattern

---
// src/components/Greeting.astro

interface Props {
  name: string;
  excited?: boolean;
}

const { name, excited = false } = Astro.props;
---

<h1>Hello, {name}{excited ? "!" : "."}</h1>

Calling It

---
import Greeting from "../components/Greeting.astro";
---

<Greeting name="Ada" />
<Greeting name="Grace" excited />
<Greeting name="Linus" excited={isExcited} />
  • Strings: name="..."
  • Booleans: excited or excited={true|false}
  • Numbers / arrays / objects: count={5}, tags={["a", "b"]}

Defaults Go In Destructuring

---
const { name, role = "user", count = 0 } = Astro.props;
---

Spreading Rest Props

---
interface Props {
  kind?: string;
  [key: string]: any;   // accept any extra HTML attrs
}
const { kind = "primary", ...rest } = Astro.props;
---

<button class={`btn btn--${kind}`} {...rest}>
  <slot />
</button>

Passing Through HTML Attributes Cleanly

For a wrapper around a native element, use Astro’s built-in HTMLAttributes helper:

---
import type { HTMLAttributes } from "astro/types";

type Props = HTMLAttributes<"button"> & {
  kind?: "primary" | "danger";
};

const { kind = "primary", ...rest } = Astro.props;
---

<button class={`btn btn--${kind}`} {...rest}>
  <slot />
</button>

The caller gets autocomplete for every legit <button> attribute, plus your custom kind.

Up Next

Beyond the default slot — named slots for multi-region layouts.

Named Slots →