Skip to content
← All questions
🔥 Advanced

What are all the compiler macros in Vue?

🔗 Composition API🔷 TypeScript🔄 v-model🎰 Slots

Compiler macros are special functions that only work inside <script setup>. They're processed at compile time and don't need to be imported. Vue 3.5 has six of them.

defineProps

Declares the props the component accepts. Returns a reactive object.

vue
<script setup lang="ts">
const props = defineProps<{
  title: string
  count?: number
}>()

// With defaults
const props = withDefaults(
  defineProps<{
    title: string
    items?: string[]
  }>(),
  {
    items: () => []
  }
)
</script>
Open in Vue Playground

defineEmits

Declares the events the component can emit. Returns a typed emit function.

vue
<script setup lang="ts">
const emit = defineEmits<{
  submit: [data: FormData]
  cancel: []
}>()

emit('submit', formData)
</script>
Open in Vue Playground

defineModel (Vue 3.4+)

Creates a two-way binding for v-model. Returns a ref that reads from the prop and emits on write.

vue
<script setup lang="ts">
const name = defineModel<string>('name', { required: true })
const checked = defineModel<boolean>({ default: false })

// With custom modifiers
const [text, modifiers] = defineModel<string>({
  set(value) {
    return modifiers.trim ? value.trim() : value
  }
})
</script>
Open in Vue Playground

defineExpose

Controls what the component exposes to parent template refs. Without it, <script setup> components expose nothing.

vue
<script setup>
import { ref } from 'vue'

const count = ref(0)
function reset() {
  count.value = 0
}

defineExpose({ count, reset })
</script>
Open in Vue Playground

defineOptions (Vue 3.3+)

Sets component options that don't have a macro equivalent, like name and inheritAttrs.

vue
<script setup>
defineOptions({
  name: 'MyComponent',
  inheritAttrs: false
})
</script>
Open in Vue Playground

Before 3.3, you needed a separate <script> block for these.

defineSlots (Vue 3.3+)

Declares slot types for TypeScript. Returns the slots object (same as useSlots()).

vue
<script setup lang="ts">
const slots = defineSlots<{
  default: (props: { item: User }) => any
  header: (props: { title: string }) => any
  empty: () => any
}>()
</script>
Open in Vue Playground

This doesn't change runtime behavior. It only provides type checking for slot props in the template and for consumers using the component.

Summary table

MacroSincePurposeReturns
defineProps3.0Declare propsReactive props object
defineEmits3.0Declare eventsTyped emit function
defineModel3.4Two-way v-model bindingWritable ref
defineExpose3.0Control public API for refsvoid
defineOptions3.3Set name, inheritAttrs, etc.void
defineSlots3.3Type slot propsSlots object

Rules that apply to all macros

  • They only work inside <script setup>, not in regular <script> or .ts files.
  • Don't import them. The compiler removes them at build time.
  • They must be called at the top level, not inside functions or conditionals.
  • defineProps and defineEmits can't be used in the same component as their Options API equivalents (props, emits).

See also: What is script setup? · What is defineExpose and when is it needed?

References

Released under the MIT License.