A Rolldown plugin that resolves complex TypeScript type arguments in Vue defineProps<T>() calls at build time, replacing them with inline type literals so Vue's compiler can understand the props without full TypeScript type resolution.
Vue's <script setup> only supports simple, inline type literals in defineProps<T>(). If T references an imported type, a type alias, or any non-trivial construct, Vue cannot extract the prop definitions at compile time.
This plugin uses the TypeScript Language Service to fully resolve the type and rewrites it as an inline object literal before Vue processes the SFC.
# npm
npm install -D rolldown-plugin-vue-macro-types
# pnpm
pnpm add -D rolldown-plugin-vue-macro-typesPeer dependencies: rolldown, typescript
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { vueMacroTypes } from 'rolldown-plugin-vue-macro-types'
export default defineConfig({
plugins: [
vueMacroTypes(),
vue(),
],
})This plugin is only useful when defineProps<T>() uses complex types that Vue's compiler cannot resolve on its own, such as imported types, type aliases, intersections, or generics. For simple inline type literals (e.g. defineProps<{ name: string }>()), Vue handles them natively and this plugin is not needed.
tsconfig(string, optional) - Path totsconfig.json. Auto-detected if omitted.
- Filters
.vuefiles containingdefineProps<using Rolldown's built-in transform filter. - Parses the
<script setup>block with oxc-parser to locate thedefineProps<T>()call and its type argument span. - Creates a virtual TypeScript file and feeds it to a TypeScript Language Service to resolve
Tinto its fully expanded type. - Serializes the resolved type back into a type literal string (handling unions, intersections, arrays, optional/readonly properties, etc.).
- Replaces the original type argument in the SFC source with the resolved literal using magic-string, preserving sourcemaps.
// types.ts
export type BaseProps = {
id: number
label: string
}
export type UserProps = BaseProps & {
role: 'admin' | 'guest'
avatar?: string
}Before:
<script setup lang="ts">
import type { UserProps } from './types'
defineProps<UserProps>()
</script>After (build time):
<script setup lang="ts">
import type { UserProps } from './types'
defineProps<{ id: number; label: string; role: 'admin' | 'guest'; avatar?: string }>()
</script>