Is it possible to effectively determine a roster of event names while implementing the defineEmits() feature in Vue 3?

Within a reusable component, my goal is to develop a simple function that creates proxies for props in order to bind them to child components. These proxies will maintain their own internal value and be initialized with the default prop value, which may be provided when instantiated in other Vue components.

Using the following code snippet as an example:

const props = defineProps({
  customFilteringToggle: Boolean,
  expanded: {
    type: Array as PropType<string[]>,
    default: []
  },
  modelValue: {
    type: Array as PropType<unknown[] | T[]>,
    default: []
  },
  page: {
    type: Number,
    default: 1
  }
});

const emit = defineEmits<{
  (e: 'update:customFilteringToggle', value: boolean): void,
  (e: 'update:expanded', value: any): void,
  (e: 'update:modelValue', value: unknown): void
  (e: 'update:page', value: number): void
}>();

/**************** Internal Properties ****************/

const createProxy = <T>(prop: () => T, event: string) => {

  const _internal = ref(prop()) as Ref<T>;

  watch(prop, value => _internal.value = value);

  return computed({
    get: () => _internal.value,
    set: value => {

      emit(event, value); // <--- throws error on `event` 'Vue: No overload matches this call.'
      _internal.value = value;

    }
  });

};

const model = createProxy(() => props.modelValue, 'update:modelValue');

const expanded = createProxy(() => props.expanded, 'update:expanded');

const page = createProxy(() => props.page, 'update:page');

const showCustomFiltering = createProxy(() => props.customFilteringToggle, 'update:customFilteringToggle');

Is it possible to derive a list of events from:

const emit = defineEmits<{
  (e: 'update:customFilteringToggle', value: any): void,
  (e: 'update:expanded', value: any): void,
  (e: 'update:modelValue', value: unknown): void
  (e: 'update:page', value: number): void
}>();

This way, when the function is called, a suggested list of events can be generated without causing errors when providing the value as text. I often utilize keyof for similar tasks, but this scenario seems more complex; if feasible at all.

If possible, I would prefer to avoid casting.

Answer №1

To obtain the parameters from call signatures, you can follow the method proposed in this particular response. Subsequently, a tuple can be transformed into an intersection:

type Overloads<T> =
  T extends {
    (...args: infer A1): infer R1;
    (...args: infer A2): infer R2;
    (...args: infer A3): infer R3;
    (...args: infer A4): infer R4
  } ? [
    (...args: A1) => R1,
    (...args: A2) => R2,
    (...args: A3) => R3,
    (...args: A4) => R4
  ] : T extends {
    (...args: infer A1): infer R1;
    (...args: infer A2): infer R2;
    (...args: infer A3): infer R3
  } ? [
    (...args: A1) => R1,
    (...args: A2) => R2,
    (...args: A3) => R3
  ] : T extends {
    (...args: infer A1): infer R1;
    (...args: infer A2): infer R2
  } ? [
    (...args: A1) => R1,
    (...args: A2) => R2
  ] : T extends {
    (...args: infer A1): infer R1
  } ? [
    (...args: A1) => R1
  ] : any

type OverloadedParameters<T> =
  Overloads<T> extends infer O ?
  { [K in keyof O]: Parameters<Extract<O[K], (...args: any) => any>>[0] } : never

type TupleToIntersection<T extends any[]> = Extract<T[number], any>; 

type EmitEvents = TupleToIntersection<OverloadedParameters<typeof emit>>;

Note that it currently handles a limited number of values (4) because of its functionality and may require expansion if needed.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

SignalR server with Redis backplane for horizontal scaling is experiencing issues with proper functionality on the Vue front end

Seeking Appreciation for Providing Answers! I have developed a SignalR backend server using .NET Core 3.1 running on Docker (Debian). Initially, it functions properly when I deploy a single server on Kubernetes. However, as soon as I scale up the replicas ...

What is the best way to show a list of integers in a datagridview?

It seems like a simple task, but I am struggling to display a list of integers on a datagridview. A quick search on Google provides plenty of results for displaying custom classes in a datagridview, but not for a simple list of integers. When I try to use ...

I recently installed bootstrap, jquery, and popper.js on my live server, but to my surprise, nothing was appearing on the screen. Despite compiling the

After successfully installing bootstrap, jquery, and popper.js, I encountered an issue on my live server where nothing was displaying. Oddly enough, no errors were detected after compiling the code. import { createApp } from 'vue' import App from ...

Using Vue.js to display svg content inside the <svg> element

One of my Vue.js components is responsible for dynamically building the content of an svg element. Let's simplify things and say that the content consists of a <circle cx="50" cy="50" r="60" /> This component achieves this by manipulating a dat ...

Make sure to call the loader function in React Router only when there are path params present

I'm currently implementing the new React Router, utilizing loader functions to fetch data based on the loaded element. My goal is to have certain APIs called regardless of the route, with additional APIs triggered for specific routes. However, I&apos ...

The error message "./components/Avatar.tsx Error: Module '@babel/preset-stage-0' not found" appeared on the screen

Even after dedicating a few hours to research, I'm still unable to resolve an ongoing issue with Babel and Webpack. ): The solution must be simple. Here is my .babelrc: { "presets": ["@babel/preset-env", "@babel/preset-reac ...

Using Vue to pass an array of rules to a child component

Currently, I am passing a set of props called "propSet" to a child component. These props are computed and detect an 'edit mode' boolean that changes accordingly. The "propSet" defines the following form input props: color, filled, dense, outlin ...

Tips for effectively waiting for createWriteStream to complete?

When it comes to async programming in node.js, callbacks are usually the way to go. However, personally, I find callback-based code challenging to read and understand. That's why I prefer using async & await whenever possible. This approach genera ...

What is the best method for consolidating all record names into a single array?

I'm currently working on a small webpage and utilizing Airtable as my database. Within my base, I have several fields, with the most crucial ones being "name" and "icon_png". Using vue.js, I log in through axios and retrieve all the database entries i ...

Encountering a problem while running npm build (PostCSS plugin postcss-purgecss needs PostCSS 8) on vuejs3 with tailwind

I'm currently in the process of developing an application using Vue.js 3 and Tailwind CSS. While testing some configurations before diving into the project, I encountered a specific error message when running npm run build: ERROR Failed to compile wit ...

Why is typescript-eslint flagging the error "Unsafe call of an any typed value" whenever I try to use the delete or update methods?

type TResultCategory<T> = { title: string; items: T[]; description?: string; delete(dispatch: Dispatch<{}>): void; update?(dispatch: Dispatch<{}>, products: TCartProduct[]): void; } type TResult = (TResultCategory<TResultPro ...

Problem encountered when trying to use the sharp package in NuxtJS

I attempted to implement this code in my Nuxt project, but it encountered an issue during compilation. Within my plugin/sharp.js file: import vue from "vue" import sharp from "sharp" vue.use(sharp) And in my nuxt.config.js file: plugi ...

Encountering issues while attempting to send a GET request with a custom header in NUXT/VUE using $fetch()

async function fetchArticles(){ await $fetch(BASE_URL + 'api/article/', { headers: { "Accept-Language": "TEST IF IT CHANGE", "Authorization": "REQUEST_TOKEN" }, ...

What are some effective ways to utilize the data gathered from a subscribe() method in a different

handleKeyUp(event: any): void { this.technologiesService.retrieveData(event.target.value) .subscribe(data => { this.myResults = data; }); } The result of data is: https://i.sstatic.net/WjiD4.png I want to assign data as a property fo ...

Encountering a problem while attempting to host an Angular application on localhost:4200

After executing the ng serve command, I encountered an issue in the browser: An error occurred while trying to resolve "localhost:4200" ("") for "10.238.0.0": rpc error: code = Unknown desc = no such record I apologize if this question seems basic, as I ...

Tips for passing data from parent component to child component efficiently (using Element UI and Vue.js)

I am currently using Element UI and I have encountered an issue with the el-switch component, which is similar to a checkbox. I am struggling to figure out how to properly integrate it within other components like el-table -> el-column -> el-switch. ...

The letter 'T' has the flexibility to be assigned with any type, even those that are completely unrelated

Currently, I am developing an endpoint within Next.js. My goal is to strictly enforce the JSON structure returned by API endpoints. It would be very beneficial if I could automatically infer the return type of an endpoint and utilize that information in my ...

Does Typescript fail to recognize the "delete" operator?

Whenever I utilize the delete operator in Typescript, it appears that the system does not recognize that the property has been eliminated. For instance: interface HasName { name: string; } interface HasNoName { name: never; } function removeName( ...

"Easy step-by-step guide on rearranging field display order in radDataForm with a JSON data

How can I rearrange the order of fields displayed when using JSON as a source in Vue.js / NativeScript (radDataForm)? Currently, my code is functioning correctly, but the displayed order is: Album Name Band Name Owned Year Borrowed This order does not m ...

"Troubleshooting: NuxtJs vue-flip feature stuck on front side, not rotating to

I have recently installed the vue-flip plugin in a NuxtJs (VueJS) project that I created using the command: npx create-nuxt-app <project-name>. In the index.vue file, I simply added: <vue-flip active-click="true"> <div slot="front"> ...