DEV Community

Keymel Gaston
Keymel Gaston

Posted on

Can You Type Named Slots in Astro? (Short Answer: Not Yet)

Someone asked me this in the Astro Discord recently, and I went looking for a real answer instead of guessing. Sharing it here because it's a question that comes up a lot, and the honest answer isn't what most people expect.

The question

You can type a component's props in Astro easily:

interface Props {
  title: string;
  description: string;
}
Enter fullscreen mode Exit fullscreen mode

And your editor gives you autocomplete and errors if you get it wrong. Great.

But what about named slots?

---
type Props = {
  children: string;
}
---
<slot />
<slot name="foo" />
Enter fullscreen mode Exit fullscreen mode

Can you type the foo slot the same way — so TypeScript warns you if a consumer misspells the slot name, or passes the wrong kind of content?

The short answer

You can't. Not properly, at least not yet.

Astro's Props typing only covers the default slot, via children:

type Props = { children: any };
Enter fullscreen mode Exit fullscreen mode

There's no equivalent for named slots. This isn't something hidden in the docs that you missed — it's a real, acknowledged gap in the framework.

It's not just me saying that

There's a GitHub RFC discussion proposing typed slots, going back to December 2022. An Astro core maintainer replied directly:

"Typed slots is already something we're planning, though it's currently not in our roadmap. The tricky part of this is mostly the implementation, TSX doesn't have proper tools for this and our current slot implementation is challenging to support, we're still investigating the way to go for that."

That's from 2022. As of writing this, it's still not implemented. The RFC author followed up in 2024 saying the problem still needs addressing — no resolution since.

Why it's actually hard, not just neglected

Props are easy to type because they're a flat object — { name: string, age: number }. TypeScript has handled that shape forever.

Slots aren't data, though — they're markup being injected into a specific spot in a component's template. That's a fundamentally different kind of thing to describe than "this value should be a string." TSX itself doesn't have great tooling for this, and Astro's internal slot implementation adds its own layer of complexity on top. It's less "nobody got around to it" and more "the tools to do it properly don't fully exist yet."

What you can actually do today

Two practical options, neither of them compile-time type safety, but both better than nothing:

1. Document it in a comment. Not enforced, but at least visible to whoever uses your component:

---
// Slots: default, "header", "footer"
type Props = { children: any };
---
Enter fullscreen mode Exit fullscreen mode

2. Runtime checks with Astro.slots.has():

---
const hasFooter = Astro.slots.has("footer");
---
{hasFooter && <slot name="footer" />}
Enter fullscreen mode Exit fullscreen mode

This catches missing slots at runtime, not compile time — but if a slot is required for your component to render correctly, at least you can branch on whether it was passed.

The actual lesson here

Not every "how do I do X" question has an answer. Sometimes the honest answer is "you can't, here's why, here's the closest workaround" — and that's more useful than a fake solution that falls apart the moment someone tries it. If you're ever unsure whether a limitation is you missing something or a real framework gap, checking the RFC discussions and issue trackers directly is worth the extra five minutes.


If you're building with Astro + GSAP + Lenis specifically, I write about that stack a bit — my last post covered 4 common bugs in that combo. Happy to talk through Astro TypeScript quirks in the comments if you've hit others like this one.

Top comments (0)