All skills
onmax avatar

/vue-debug-guides

@de09c7b official
by Maxonmax/nuxt-skills715 stars
38

Vue 3 debugging and error handling for runtime errors, warnings, async failures, and SSR/hydration issues. Use when diagnosing or fixing Vue issues.

Use this Skill: https://skilld.dev/gh/onmax/nuxt-skills/vue-debug-guides

This session only. Nothing lands on disk.

referencets-event-handler-explicit-typing.md

≈1.6k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Always Explicitly Type Event Handlers

Impact: MEDIUM - Native DOM event handlers in Vue components have implicit any type for the event parameter. In TypeScript strict mode, this causes errors. You must explicitly type event parameters and use type assertions for event.target.

Task Checklist

  • Always type the event parameter explicitly (e.g., Event, MouseEvent)
  • Use type assertions when accessing element-specific properties
  • Consider using inline handlers for simple cases
  • Be aware of Vue's synthetic event system

The Problem

<script setup lang="ts">
// WRONG: event has implicit 'any' type
function handleChange(event) {  // Error in strict mode!
  console.log(event.target.value)  // Also error: target might be null
}

// WRONG: Missing type assertion for element access
function handleInput(event: Event) {
  console.log(event.target.value)  // Error: 'value' doesn't exist on EventTarget
}
</script>

<template>
  <input @change="handleChange" @input="handleInput" />
</template>

The Solution

<script setup lang="ts">
// CORRECT: Explicit Event type + type assertion
function handleChange(event: Event) {
  const target = event.target as HTMLInputElement
  console.log(target.value)
}

// CORRECT: Specific event type when needed
function handleClick(event: MouseEvent) {
  console.log(event.clientX, event.clientY)
}

function handleKeydown(event: KeyboardEvent) {
  if (event.key === 'Enter') {
    submitForm()
  }
}

function handleSubmit(event: SubmitEvent) {
  event.preventDefault()
  const formData = new FormData(event.target as HTMLFormElement)
}
</script>

<template>
  <input @change="handleChange" />
  <button @click="handleClick">Click</button>
  <input @keydown="handleKeydown" />
  <form @submit="handleSubmit">...</form>
</template>

Common Event Types

Event Type Common Properties
click, dblclick MouseEvent clientX, clientY, button
keydown, keyup, keypress KeyboardEvent key, code, ctrlKey, shiftKey
input, change Event target (needs assertion)
focus, blur FocusEvent relatedTarget
submit SubmitEvent submitter
drag, dragstart, drop DragEvent dataTransfer
wheel, scroll WheelEvent deltaX, deltaY
touch events TouchEvent touches, changedTouches

Element-Specific Type Assertions

<script setup lang="ts">
// HTMLInputElement for text, number, checkbox, radio inputs
function handleTextInput(event: Event) {
  const input = event.target as HTMLInputElement
  console.log(input.value, input.checked)
}

// HTMLSelectElement for select dropdowns
function handleSelect(event: Event) {
  const select = event.target as HTMLSelectElement
  console.log(select.value, select.selectedIndex)
}

// HTMLTextAreaElement for textareas
function handleTextarea(event: Event) {
  const textarea = event.target as HTMLTextAreaElement
  console.log(textarea.value, textarea.selectionStart)
}

// HTMLFormElement for forms
function handleFormSubmit(event: SubmitEvent) {
  event.preventDefault()
  const form = event.target as HTMLFormElement
  const formData = new FormData(form)
}
</script>

Inline Event Handler Pattern

For simple cases, inline handlers with type annotations work well:

<template>
  <!-- Inline with type assertion -->
  <input
    @input="(event: Event) => {
      const input = event.target as HTMLInputElement
      searchQuery = input.value
    }"
  />

  <!-- Or with $event cast -->
  <input @input="searchQuery = ($event.target as HTMLInputElement).value" />
</template>

Generic Handler Pattern

Create reusable typed handlers:

// utils/events.ts
export function getInputValue(event: Event): string {
  return (event.target as HTMLInputElement).value
}

export function getSelectValue(event: Event): string {
  return (event.target as HTMLSelectElement).value
}

export function getCheckboxChecked(event: Event): boolean {
  return (event.target as HTMLInputElement).checked
}
<script setup lang="ts">
import { getInputValue, getCheckboxChecked } from '@/utils/events'

const name = ref('')
const agreed = ref(false)
</script>

<template>
  <input @input="e => name = getInputValue(e)" />
  <input type="checkbox" @change="e => agreed = getCheckboxChecked(e)" />
</template>

Vue Component Events

For Vue component events (not DOM events), use defineEmits for type safety:

<script setup lang="ts">
const emit = defineEmits<{
  'custom-event': [data: { id: number; name: string }]
}>()

// Handler for child component event
function handleChildEvent(data: { id: number; name: string }) {
  console.log(data.id, data.name)
}
</script>

<template>
  <!-- Custom component event - properly typed -->
  <ChildComponent @custom-event="handleChildEvent" />
</template>

Avoiding currentTarget vs target Confusion

function handleClick(event: MouseEvent) {
  // target: The element that triggered the event (could be a child)
  const target = event.target as HTMLElement

  // currentTarget: The element the listener is attached to
  const currentTarget = event.currentTarget as HTMLButtonElement

  // Be explicit about which you need
  if (target.tagName === 'SPAN') {
    // Clicked on span inside button
  }
}

Reference

Source: SKILL.md on GitHub

No alerts9d3 checks · Risk SAFE
  • Gen Agent Trust Hub9d

    The skill is a comprehensive collection of Vue 3 debugging guides and best practices. It contains no malicious code, exfiltration attempts, or prompt injections.

  • Socket9d

    No alerts

  • Snyk9d

    Risk: LOW · No issues

Signed by skilld at de09c7b. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 3 days ago.

Activeupdated last week

README badge

README badge for onmax/nuxt-skills/vue-debug-guides