`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.
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:
excitedorexcited={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 →