在 Vue 3 + TypeScript 中,使用 defineEmits 配合泛型类型声明自定义事件,支持调用签名语法和对象字面量语法两种方式,实现事件名、参数个数及类型的强校验与 IDE 智能提示。

在 Vue 3 + TypeScript 中,为自定义事件 emit 声明强类型参数结构,核心是用 defineEmits 配合类型定义,让事件名、参数个数和类型全部可校验、可提示、可追溯。
用 defineEmits 声明类型(推荐组合式 API)
在 <script setup lang="ts"> 中调用 defineEmits,传入一个泛型类型,明确每个事件的签名:
- 支持两种写法:「调用签名语法」更灵活,适合复杂场景;「对象字面量语法」更简洁,Vue 3.3+ 官方推荐
- IDE 能据此自动补全事件名和参数,拼错事件或传错类型会在编辑器直接报错
- 不声明类型时,
emit默认是(event: string, ...args: any[]) => void,完全失去类型保护
调用签名语法(适合带文档/多参数/重载)
把每个事件写成函数签名形式,支持 JSDoc 注释,语义清晰:
const emit = defineEmits<{
/**
* 更新弹窗可见状态
* @param visible boolean 值
*/
(e: "update:visible", visible: boolean): void;
<p>/**</p><div class="aritcle_card flexRow">
<div class="artcardd flexRow">
<a class="aritcle_card_img" href="/xiazai/skill8025" title="Ainative Vue Sdk"><img
src="https://img.php.cn/upload/skill/000/000/081/179180111122467.jpg" alt="Ainative Vue Sdk" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a href="/xiazai/skill8025" title="Ainative Vue Sdk">Ainative Vue Sdk</a>
<p>使用 `@ainative/vue-sdk` 为 Vue 3 应用添加 AI 聊天功能。适用于以下场景:(1) 安装 `@ainative/vue-sdk`,(2) 在 Vue 组件中使用 `useChat` 组合式函数,(3) 提供……</p>
</div>
<a href="/xiazai/skill8025" title="Ainative Vue Sdk" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a>
</div>
</div><p><span>立即学习</span>“<a href="https://pan.quark.cn/s/cb6835dc7db1" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">前端免费学习笔记(深入)</a>”;</p><ul><li>提交表单数据</li><li>@param data 表单有效载荷
*/
(e: "submit", data: { name: string; age?: number }): void;</li></ul><p>/**</p><p><span>立即学习</span>“<a href="https://pan.quark.cn/s/cb6835dc7db1" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">前端免费学习笔记(深入)</a>”;</p><ul><li>取消操作(无参)
*/
(e: "cancel"): void;
}>();触发时必须严格匹配签名:emit("submit", { name: "Alice" }) ✅,emit("submit", "wrong") ❌ 编译报错。
对象字面量语法(简洁直观,推荐日常使用)
键是事件名,值是参数元组类型,顺序和类型一一对应:
const emit = defineEmits<{
"update:modelValue": [value: string]; // 单参数,带别名提升可读性
change: [id: number; status: "active" | "inactive"]; // 多参数,支持联合类型
reset: []; // 空参数,必须写空数组
}>();注意:元组中每个元素都需有明确类型,[string, number] 和 [number, string] 是不同类型,顺序错即报错。
配合 props 实现双向绑定类型安全
比如组件接收 modelValue 并触发 update:modelValue,可以统一用泛型约束:
const props = defineProps<{ modelValue: string }>();
const emit = defineEmits<{ "update:modelValue": [value: string] }>();
<p>// 触发时自动校验 value 类型是否为 string
const handleChange = () => emit("update:modelValue", props.modelValue.toUpperCase());这样父组件传入的 v-model:value 和子组件 emit 的参数类型就完全对齐,避免运行时类型错位。

















