0Pricing
Vue Academy · Lesson

Typed Props and Emits with defineProps/defineEmits

Generic defineProps (), complex types, optional props, emit typing.

Typed Props and Emits with defineProps/defineEmits is a free Vue Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Vue Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Typing Component Inputs and Outputs

With lang="ts", the defineProps and defineEmits macros accept TypeScript types directly. This gives compile-time checks on what data flows in and out of a component.

Props From an Interface

Pass a type to the defineProps generic. An interface keeps complex prop shapes readable and reusable.

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

Inline Type Literals

For small components an inline object type is fine — no separate interface needed.

<script setup lang="ts">
const props = defineProps<{
  label: string
  disabled: boolean
}>()
</script>

Optional Properties With ?

Mark a property optional with ?. Optional props are typed as T | undefined and the parent may omit them.

<script setup lang="ts">
interface Props {
  title: string
  subtitle?: string
}
const props = defineProps<Props>()
</script>

Complex Prop Types

Props can be arrays, unions, or object shapes — anything TypeScript can express.

<script setup lang="ts">
interface Props {
  items: string[]
  size: 'sm' | 'md' | 'lg'
  user: { id: number; name: string }
}
const props = defineProps<Props>()
</script>

Defaults With withDefaults

The type-only form cannot hold defaults, so wrap it in withDefaults. The second argument maps prop names to default values.

<script setup lang="ts">
const props = withDefaults(defineProps<{
  size?: string
  count?: number
}>(), {
  size: 'md',
  count: 0
})
</script>

Defaults for Objects and Arrays

Object and array defaults must be returned from a factory function, just as in the Options API, to avoid sharing one instance across components.

withDefaults(defineProps<{
  tags?: string[]
}>(), {
  tags: () => []
})

Declaring Typed Emits

defineEmits can take a type that lists each event and its payload as a call signature. This catches wrong payload types at compile time.

<script setup lang="ts">
const emit = defineEmits<{
  (e: 'change', value: string): void
  (e: 'delete', id: number): void
}>()
</script>

Emitting Typed Payloads

Now emit only accepts valid event names and matching payload types. Passing a number where a string is expected is a compile error.

function rename(name: string) {
  emit('change', name) // ok
  // emit('change', 123) // type error
}

The Named Tuple Syntax

Vue 3.3+ supports a shorthand object form where each event maps to a tuple of its argument types — cleaner than call signatures.

<script setup lang="ts">
const emit = defineEmits<{
  change: [value: string]
  delete: [id: number]
}>()
</script>

Props and Emits Together

A typical typed component declares both: inputs via defineProps and outputs via defineEmits, fully checked end to end.

<script setup lang="ts">
defineProps<{ modelValue: string }>()
const emit = defineEmits<{
  'update:modelValue': [value: string]
}>()
</script>

Quick Check

Test your knowledge of typed props and emits.

Recap

You learned typed component I/O:

  • Pass an interface or inline type to defineProps<T>().
  • Use ? for optional props and withDefaults for defaults (factory for objects/arrays).
  • defineEmits<T>() types event names and payloads.
  • The tuple form (event: [payload]) is the modern shorthand.

Frequently asked questions

Is the “Typed Props and Emits with defineProps/defineEmits” lesson free?

Yes — the full text of “Typed Props and Emits with defineProps/defineEmits” is free to read here on the web, and the Vue Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Vue Academy course, upgrade to CoddyKit PRO.

What will I learn in “Typed Props and Emits with defineProps/defineEmits”?

Generic defineProps (), complex types, optional props, emit typing. You practise Vue Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Vue Academy?

No prior experience is required. Vue Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Typed Props and Emits with defineProps/defineEmits” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Vue Academy lesson?

Yes. Every Vue Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. TypeScript Setup in Vue Projects
  2. Typed Props and Emits with defineProps/defineEmits
  3. Typing Composables and Refs
  4. Generic Vue Components
← Back to Vue Academy