The Problem
Vue components have a built-in mechanism called $attrs fallthrough that allows arbitrary HTML attributes to pass through to child elements. This works automatically when a Vue component has a single root element, or can be explicitly controlled using the $attrs object.
However, Astro’s language tools weren’t aware of this Vue feature. When developers tried to pass standard HTML attributes like class, style, or id to Vue components in .astro files, TypeScript would throw false errors even though the code worked perfectly at runtime.
For example, this valid code would trigger TypeScript errors:
---
import MyVueComponent from './MyVueComponent.vue';
---
<!-- This works at runtime but TypeScript complained -->
<MyVueComponent class="my-styles" id="hero-section" />
The issue was labeled as a “good first issue” and had been open since October 2022, affecting developers who wanted to style Vue components using standard HTML attributes in their Astro projects.
The Solution
I implemented a type helper system that extends Vue component props to include HTML attributes and Astro client directives. The solution follows the same pattern already established in Astro’s Svelte integration.
The fix introduces a PropsWithHTMLAttributes<T> type that combines:
- Component-specific props (
T) - the props explicitly defined in the Vue component - Standard HTML attributes from
astroHTML.JSX.HTMLAttributes- class, style, id, data-*, etc. - Astro client directives (
AstroClientDirectives) - client:load, client:visible, etc.
Here’s the core type definition that makes this work:
// vue-shims.d.ts
type PropsWithHTMLAttributes<T> = T &
astroHTML.JSX.HTMLAttributes &
AstroClientDirectives;
The editor.cts file was then updated to automatically wrap all generated Vue component props with this new helper type, ensuring TypeScript recognizes that Vue components can accept any valid HTML attribute.
Files Changed
| File | Change |
|---|---|
packages/integrations/vue/vue-shims.d.ts | New file defining the PropsWithHTMLAttributes<T> type |
packages/integrations/vue/src/editor.cts | Updated to wrap Vue props with HTML attributes type |
packages/integrations/vue/package.json | Added export for the new type definitions |
packages/integrations/vue/test/toTsx.test.js | Added test coverage with astro check validation |
Timeline
| Date | Event |
|---|---|
| Oct 5, 2022 | Issue #14686 opened by @Princesseuh |
| Dec 13, 2025 | Analyzed root cause and submitted PR #15016 |
| Dec 17, 2025 | Rebased branch to resolve mixed commit history |
| Jan 7, 2026 | PR approved and merged by @Princesseuh |
Impact
This fix benefits all Astro developers using Vue components who want to:
- Apply CSS classes directly to Vue components
- Add inline styles for quick customizations
- Use data attributes for JavaScript interactions
- Set accessibility attributes like
aria-*androle - Use Astro’s client directives for partial hydration
The solution aligns Vue’s TypeScript support with the existing Svelte integration pattern, ensuring a consistent developer experience across Astro’s framework integrations.