--- title: defineEmits Must Be Used at Top Level of script setup impact: HIGH impactDescription: Using defineEmits inside functions causes compilation errors - macros must be at module scope type: gotcha tags: [vue3, defineEmits, script-setup, macros, composition-api] --- # defineEmits Must Be Used at Top Level of script setup **Impact: HIGH** - The `defineEmits()` macro can only be used directly within ` ``` **Incorrect - Inside a conditional:** ```vue ``` **Incorrect - Referencing local variables:** ```vue ``` ## Correct Usage **Correct - Top level declaration:** ```vue ``` **Correct - With TypeScript types:** ```vue ``` **Correct - Using constant arrays (compile-time constant):** ```vue ``` ## Why This Restriction Exists Vue's compiler processes ` ``` ```js // composables/useFormEvents.js export function useFormEvents(emit) { function handleSubmit(data) { emit('submit', data) } function handleCancel() { emit('cancel') } return { handleSubmit, handleCancel } } ``` ## ESLint Rule The `eslint-plugin-vue` provides the `vue/valid-define-emits` rule that catches these errors: ```js // eslint.config.js export default [ { rules: { 'vue/valid-define-emits': 'error' } } ] ``` This rule reports: - `defineEmits` used inside functions - `defineEmits` referencing local variables - Multiple `defineEmits` calls in the same component - `defineEmits` used outside `