---
title: Always Explicitly Type Event Handlers
impact: MEDIUM
impactDescription: Without explicit typing, event parameters have implicit 'any' type causing TypeScript errors in strict mode
type: gotcha
tags: [vue3, typescript, events, dom-events, composition-api]
---
# 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
```vue
```
## The Solution
```vue
```
## 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
```vue
```
## Inline Event Handler Pattern
For simple cases, inline handlers with type annotations work well:
```vue
{
const input = event.target as HTMLInputElement
searchQuery = input.value
}"
/>
```
## Generic Handler Pattern
Create reusable typed handlers:
```typescript
// 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
}
```
```vue
name = getInputValue(e)" />
agreed = getCheckboxChecked(e)" />
```
## Vue Component Events
For Vue component events (not DOM events), use `defineEmits` for type safety:
```vue
```
## Avoiding currentTarget vs target Confusion
```typescript
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
- [Vue.js TypeScript with Composition API - Event Handlers](https://vuejs.org/guide/typescript/composition-api.html#typing-event-handlers)
- [MDN Event Reference](https://developer.mozilla.org/en-US/docs/Web/Events)
- [TypeScript DOM Types](https://github.com/microsoft/TypeScript/blob/main/lib/lib.dom.d.ts)