组件部分代码src\components\common\WorkflowMainDialog.vueinterface Props { /** 对话框标题 */ title?: string; /** 活动实例包含必要信息 */ activityInstance: ActivityInstance; /** 校验数据返回 false 或 reject 则return */ validate?: () boolean | Promiseboolean; /** 保存函数接收一个 done 回调保存完成后调用 */ onSave?: (done: () void) void | Promisevoid; } const props withDefaults(definePropsProps(), { title: 流程办理, validate: undefined, onSave: undefined }); const emit defineEmits{ /** * 已办理办理/退回后 */ audited: []; /** * 保存已通过 onSave 处理此事件可作为额外通知 */ save: []; }();defineProps定义了onSavedefineEmits定义了save造成命名冲突使用组件WorkflowMainDialog v-ifstore.currentCapitalAllocate?.activityInstance refcapitalAllocateWorkflowInstanceDialogRef title资金分配 :activity-instancestore.currentCapitalAllocate?.activityInstance :validatevalidateAllocate :onSavehandleSaveAllocate auditedhandleAudited报错如下不能将类型“(done: () void) Promisevoid”分配给类型“((done: () void) void | Promisevoid) (() any)”。 不能将类型“(done: () void) Promisevoid”分配给类型“() any”。 目标签名提供的自变量太少。预期为 1 个或更多但实际为 0 个。ts-plugin(2322) WorkflowMainDialog.vue(40, 3): 所需类型来自属性 onSave在此处的 { readonly title?: string | undefined; readonly activityInstance: ActivityInstance; readonly loading?: boolean | undefined; readonly isModified?: boolean | undefined; ... 5 more ...; readonly onAudited?: (() any) | undefined; } VNodeProps AllowedComponentProps ComponentCustomProps Record... 类型上声明该属性 通义灵码一键修复 (property) onSave?: (((done: () void) void | Promisevoid) (() any)) | undefined 保存函数接收一个 done 回调保存完成后调用您遇到的类型错误确实是由于defineEmits中声明了save事件导致 Vue 自动生成一个同名的onSaveprop类型为() any与您在defineProps中自定义的onSave类型(done: () void) void | Promisevoid合并为交叉类型无法兼容。即使父组件没有使用save类型系统仍然会认为组件可能接收这个 prop因此冲突依然存在。解决方案1. 修改自定义 prop 名称推荐将onSave改为不与事件监听器冲突的名称例如saveHandler。修改组件内部tsinterface Props { // ... /** 保存函数接收一个 done 回调保存完成后调用 */ saveHandler?: (done: () void) void | Promisevoid; // 改名 } // 使用处 const buttonSaveDisabled computed( () props.loading || auditLoading.value || props.saving || !props.isModified || !props.saveHandler ); const handleSaveWithDone async (event?: MouseEvent, done?: () void) { if (props.saveHandler) { await props.saveHandler(() { done?.(); emit(save); // 可选仍可触发 save 事件 }); } else { done?.(); } };模板中vueBasePreventReClickButtonEmit v-ifsaveHandler classshort-btn typeprimary plain :disabledbuttonSaveDisabled :timeout0 clickhandleSaveWithDone 保存 /BasePreventReClickButtonEmit父组件使用时vueWorkflowMainDialog ... :save-handlerhandleSaveAllocate auditedhandleAudited saveonSaveComplete !-- 可选 -- 2. 如果不需要save事件可以从defineEmits中移除tsconst emit defineEmits{ audited: []; // 移除 save 事件 }();但保留事件有时是有用的比如父组件想监听保存完成做额外操作。因此方案 1 更灵活。为什么必须改名因为 Vue 的script setup会自动为defineEmits中声明的事件生成对应的 props命名规则onXxx类型为((...args: any[]) any) | undefined。这些 props 会与您在defineProps中声明的同名的 prop 合并导致 TypeScript 要求您的 prop 同时满足两种签名。改名后自定义 propsaveHandler与自动生成的onSave不再冲突问题解决。
Vue3中defineProps(定义onSave)与defineEmits(定义save)造成命名冲突
组件部分代码src\components\common\WorkflowMainDialog.vueinterface Props { /** 对话框标题 */ title?: string; /** 活动实例包含必要信息 */ activityInstance: ActivityInstance; /** 校验数据返回 false 或 reject 则return */ validate?: () boolean | Promiseboolean; /** 保存函数接收一个 done 回调保存完成后调用 */ onSave?: (done: () void) void | Promisevoid; } const props withDefaults(definePropsProps(), { title: 流程办理, validate: undefined, onSave: undefined }); const emit defineEmits{ /** * 已办理办理/退回后 */ audited: []; /** * 保存已通过 onSave 处理此事件可作为额外通知 */ save: []; }();defineProps定义了onSavedefineEmits定义了save造成命名冲突使用组件WorkflowMainDialog v-ifstore.currentCapitalAllocate?.activityInstance refcapitalAllocateWorkflowInstanceDialogRef title资金分配 :activity-instancestore.currentCapitalAllocate?.activityInstance :validatevalidateAllocate :onSavehandleSaveAllocate auditedhandleAudited报错如下不能将类型“(done: () void) Promisevoid”分配给类型“((done: () void) void | Promisevoid) (() any)”。 不能将类型“(done: () void) Promisevoid”分配给类型“() any”。 目标签名提供的自变量太少。预期为 1 个或更多但实际为 0 个。ts-plugin(2322) WorkflowMainDialog.vue(40, 3): 所需类型来自属性 onSave在此处的 { readonly title?: string | undefined; readonly activityInstance: ActivityInstance; readonly loading?: boolean | undefined; readonly isModified?: boolean | undefined; ... 5 more ...; readonly onAudited?: (() any) | undefined; } VNodeProps AllowedComponentProps ComponentCustomProps Record... 类型上声明该属性 通义灵码一键修复 (property) onSave?: (((done: () void) void | Promisevoid) (() any)) | undefined 保存函数接收一个 done 回调保存完成后调用您遇到的类型错误确实是由于defineEmits中声明了save事件导致 Vue 自动生成一个同名的onSaveprop类型为() any与您在defineProps中自定义的onSave类型(done: () void) void | Promisevoid合并为交叉类型无法兼容。即使父组件没有使用save类型系统仍然会认为组件可能接收这个 prop因此冲突依然存在。解决方案1. 修改自定义 prop 名称推荐将onSave改为不与事件监听器冲突的名称例如saveHandler。修改组件内部tsinterface Props { // ... /** 保存函数接收一个 done 回调保存完成后调用 */ saveHandler?: (done: () void) void | Promisevoid; // 改名 } // 使用处 const buttonSaveDisabled computed( () props.loading || auditLoading.value || props.saving || !props.isModified || !props.saveHandler ); const handleSaveWithDone async (event?: MouseEvent, done?: () void) { if (props.saveHandler) { await props.saveHandler(() { done?.(); emit(save); // 可选仍可触发 save 事件 }); } else { done?.(); } };模板中vueBasePreventReClickButtonEmit v-ifsaveHandler classshort-btn typeprimary plain :disabledbuttonSaveDisabled :timeout0 clickhandleSaveWithDone 保存 /BasePreventReClickButtonEmit父组件使用时vueWorkflowMainDialog ... :save-handlerhandleSaveAllocate auditedhandleAudited saveonSaveComplete !-- 可选 -- 2. 如果不需要save事件可以从defineEmits中移除tsconst emit defineEmits{ audited: []; // 移除 save 事件 }();但保留事件有时是有用的比如父组件想监听保存完成做额外操作。因此方案 1 更灵活。为什么必须改名因为 Vue 的script setup会自动为defineEmits中声明的事件生成对应的 props命名规则onXxx类型为((...args: any[]) any) | undefined。这些 props 会与您在defineProps中声明的同名的 prop 合并导致 TypeScript 要求您的 prop 同时满足两种签名。改名后自定义 propsaveHandler与自动生成的onSave不再冲突问题解决。