You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue.js 2.7 script setup中defineEmits传入组合式函数的TS问题

Vue 2.7 script setup中defineEmits传入组合式函数报TS2322的原因及解决

问题根源

这完全是TypeScript类型不兼容导致的,和运行时逻辑无关——Vue 2.7对script setup里的defineEmits做了严格的类型强化,返回的emit函数是绑定了你声明的事件列表的严格类型;而选项式API的setup参数里的emit是宽松的(event: string, ...args: any[]) => void类型,自然能兼容你的组合式函数useIcomActCompatibility的参数要求。

举个具体例子:
如果你在script setup里这样声明emits:

const emit = defineEmits<{
  'icon-click': [id: string]
}>()

此时emit的类型是(e: 'icon-click', id: string) => void,只能触发icon-click事件且参数必须是string类型;但你的组合式函数如果接受的是(event: string, ...args: any[]) => void这种宽松类型,TS就会抛出TS2322错误,因为严格类型无法赋值给宽松类型(反过来则可以)。

解决方法

根据你的需求选对应的方案:

  • 方案1:给组合式函数绑定严格的emit类型
    把组件里defineEmits返回的emit类型传递给组合式函数,保证类型完全匹配:

    // 组件内
    const emit = defineEmits<{
      'icon-click': [id: string]
    }>()
    // 组合式函数
    type IconEmit = typeof emit
    export function useIcomActCompatibility(emit: IconEmit) {
      // 逻辑代码
    }
    
  • 方案2:放宽组合式函数的emit参数类型
    如果组合式函数是通用型的,不想绑定特定组件的事件列表,可以用Vue内置的EmitFn类型或者手动声明宽松类型:

    import type { EmitFn } from 'vue'
    // 或者手动定义:type EmitFn = (event: string, ...args: any[]) => void
    export function useIcomActCompatibility(emit: EmitFn) {
      // 逻辑代码
    }
    // 组件内调用时用类型断言
    useIcomActCompatibility(emit as EmitFn)
    
  • 方案3:关闭严格emit类型检查(不推荐)
    在tsconfig.json里禁用Vue的严格emit类型校验,这样defineEmits返回的emit会和选项式API的emit类型一致:

    {
      "compilerOptions": {
        // 你的其他配置
      },
      "vueCompilerOptions": {
        "strictEmits": false
      }
    }
    

    注意:这种方式会失去TS对emit事件的类型保护,不建议在大型项目中使用。

内容的提问来源于stack exchange,提问作者F.A.M.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 05:10:26