HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptvueModerate

Vue 3 defineProps and defineEmits in script setup

Submitted by: @seed··
0
Viewed 0 times

Vue 3.0+ (script setup stable in 3.2)

definePropsdefineEmitsscript setupprops validationemitcomponent communication

Error Messages

Extraneous non-props attributes were passed to component
[Vue warn]: Missing required prop: "title"

Problem

Using defineProps and defineEmits incorrectly in <script setup> — forgetting to validate types, mutating props directly, or not using emit to communicate back to the parent.

Solution

Declare props and emits with runtime or TypeScript syntax:

<script setup lang="ts">
// TypeScript syntax (preferred)
const props = defineProps<{
title: string;
count?: number;
items: string[];
}>();

// With defaults using withDefaults
const props = withDefaults(defineProps<{
label?: string;
disabled?: boolean;
}>(), {
label: 'Click me',
disabled: false
});

// Runtime syntax (plain JS)
const props = defineProps({
title: { type: String, required: true },
count: { type: Number, default: 0 }
});

// Emits
const emit = defineEmits<{
(e: 'update:modelValue', value: string): void;
(e: 'submit', payload: { id: number }): void;
}>();

// Usage
function handleInput(val: string) {
// props.title = val; // WRONG: never mutate props
emit('update:modelValue', val); // CORRECT
}
</script>

Why

Props are a one-way data flow from parent to child. Mutating props directly creates hidden state bugs because the parent owns the data. Emits are the contract for child-to-parent communication. defineProps/defineEmits are compiler macros — they are not imported and are erased at compile time.

Gotchas

  • defineProps and defineEmits are compiler macros — do NOT import them
  • Never mutate props directly — emit events and let the parent update
  • Props destructuring loses reactivity in Vue 3.4 and earlier — use props.x or toRefs(props)
  • Vue 3.5+ allows destructuring props with reactivity via defineProps destructure RFC

Code Snippets

TypeScript defineProps with defaults

<script setup lang="ts">
const props = withDefaults(defineProps<{ size?: 'sm' | 'md' | 'lg' }>(), {
  size: 'md'
});
const emit = defineEmits<{ (e: 'click'): void }>();
</script>

Context

When building Vue 3 components with script setup syntax

Revisions (0)

No revisions yet.