typescriptvue.jsvuejs3

How can I define an emit with a return type different from void in Vue 3.3+ ? (TypeScript)


From Vue 3.3 is possible to define emits in TypeScript like this

<script setup lang="ts">
const emit = defineEmits<{
  change: [id: number]
  update: [value: string]
}>()
</script>

How can I do it if I want a return type different from void, like a String?


Solution

  • Unfortunately in a core an event emitter pattern doesn't provide any return value.

    But given that all event handlers are bound with onXXX properties you can type the event returned values. Though this doesn't use the emit mechanism and because of that could have some drawbacks I'm not aware of in the context of your use case.

    And also note that we lose typing in the App.vue due fallback attributes.

    See on Vue SFC Playground

    <script setup lang="ts">
    import Wrapper from './Wrapper.vue';
    </script>
    
    <template>
      <wrapper @event="() => 'app handled'"/>
    </template>
    

    Wrapper.vue

    <script setup lang="ts">
    import Comp from './Comp.vue';
    
    </script>
    
    <template>
      <comp @event="() => 'wrapper handled'"/>
    </template>
    

    Comp.vue:

    <script setup lang="ts">
    
    const props = defineProps<{
      onEvent: (() => string) | Array<() => string>,
    }>();
    
    function onClick(){
      const handlers = Array.isArray(props.onEvent) ? props.onEvent : [props.onEvent];
      for(const fn of handlers){
        alert(fn());
      }
    }
    
    </script>
    <template>
      <button @click="onClick">Click</button>
    </template>