Ensuring type signatures are maintained when wrapping Vue computed properties and methods within the Vue.extend constructor

Currently, I am trying to encapsulate all of my defined methods and computed properties within a function that tracks their execution time.

I aim to keep the IntelliSense predictions intact, which are based on the type signature of Vue.extend({...

However, I have struggled to create my own method that can handle the complex type signature without resorting to copying numerous files from the vue.d.ts typings.

Although I have had some success by substituting Vue.extend before invoking it, my preference would be to have my own constructor method with the same typing advantages as Vue's.

Here is an example that works but is bulky, requiring "noImplicitThis": false in .tsconfig:

<template>
    <div>
        {{ computedValue }}
    </div>
</template>

<script lang="ts">
    import Vue from 'vue';

    const ext = Vue.extend;
    Vue.extend = function (x: any, ...rest:any[]) {
        const f = x.computed.computedValue;
        console.log(x, rest);
        x.computed.computedValue = function () {
            const start = Date.now();
            const rtn = f.call(this, x, ...rest);
            console.log(`Took ${(Date.now() - start) / 1000} seconds`);
            return rtn;
        }
        return ext.call(this, x, ...rest);
    } as any

    const component = Vue.extend({
        computed: {
            computedValue() {
                return 'passed';
            }
        }
    });
    Vue.extend = ext;
    export default component;
</script>

My goal is to have a method that replaces Vue.extend, wrapping the computed properties and methods in a chronometer while still maintaining IntelliSense for the component.

As of now, my implementation is cumbersome and requires significant intervention in each component's implementation to be implemented.

Answer №1

As I crafted the example component, I successfully implemented my desired outcome: a single method that incorporates Vue.extend while integrating a timer on specific component methods.

import Vue from 'vue';
import { ThisTypedComponentOptionsWithArrayProps } from 'vue/types/options';
import { ExtendedVue } from 'vue/types/vue';

export function wrap<Data, Methods, Computed, PropNames extends string = never>
    (options: ThisTypedComponentOptionsWithArrayProps<Vue, Data, Methods, Computed, PropNames>): 
    ExtendedVue<Vue, Data, Methods, Computed, Record<PropNames, any>> {
    if ('computed' in options) {
        Object.keys(options.computed as any).forEach((key: string) => {
            const f: Function = (options.computed as any)[key] as any as Function;
            (options.computed as any)[key] = function (...args: any[]) {
                const start = Date.now();
                const rtn = f.apply(this, args);
                console.log(`${key} took ${(Date.now() - start) / 1000} seconds.`);
                return rtn;
            };
        });
    }
    if ('methods' in options) {
        Object.keys(options.methods as any).forEach((key: string) => {
            const f: Function = (options.methods as any)[key] as any as Function;
            (options.methods as any)[key] = function (...args: any[]) {
                const start = Date.now();
                const rtn = f.apply(this, args);
                console.log(`${key} took ${(Date.now() - start) / 1000} seconds.`);
                return rtn;
            };
        });
    }
    return Vue.extend(options);
}

Simply use wrap({...componentOptions}) instead of

Vue.extend({...componentOptions})
to activate the timer.

$options may cause issues, but employing a clever workaround seems to prevent errors.

    export default wrap({
        ...{
            a: 4
        },
    });

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

Tips for packaging a Node TypeScript/JavaScript library using Webpack

I am currently working on a Node project with the following setup: Written in Typescript Using Webpack and ts-loader for bundling Targeting Node.js +-proj/ +-src/ |-file1.ts |-file2.ts |-file3.ts |-... |-package.json |-webpack.confi ...

The Vue component's TypeScript object prop type does not match the expected value

Having trouble with the type of Object properties in Vue Single File Components using TypeScript (created with Vue CLI 3)? Check out the example below to see the issue. The type of this.product is currently showing as (() => any) | ComputedOptions<a ...

Fasten the component to various keys

I am facing a challenge with a component that requires repainting or rebuilding due to two attributes that are not reactive (it is a wrapped jQuery component). <component :template="template" :submit="submit" :data="data"></component> After s ...

What is the syntax for declaring a variable as a string or a function with parameters?

Is it possible to define a variable in TypeScript like a string or as a Function, but with specific parameters? I am aware of how to define a string actionGetData: string; and a function actionLoaded?(event: any, ui: any): void;, but when I try to define ...

React Nextjs implementation of a fixed navigation bar to stick at the top

Hello, I am experiencing some issues setting up a sticky navbar in Next.js. The current navbar doesn't seem to be functioning as expected. Is there anyone who can assist me with the code provided below? import React, { useEffect } from 'react&apo ...

Exploring the Wonder of MVC with Ajax Calls Handling Multiple Parameters

I've been struggling to send 2 parameters from the View to the controller using an ajax call. Everything was working fine when I had only one parameter, but as soon as I added another, the function stopped working. Below is the Javascript code with a ...

Mastering the integration of dayjs within a Vue 3 application and component for optimal functionality

I have successfully integrated dayjs into a Vue3 component by including it in the data() function. import dayjs from 'dayjs' export default { data() { return { dayjs } } } While this method allows me to use dayjs within the te ...

Waiting for VueX to execute the mutation

Can VueX be used to create a method in the mounted() function that waits for a mutation in another component to be executed? Sometimes this mutation is triggered before and other times after, so I am curious if it's possible to await its execution af ...

The Javascript executor in Selenium is delivering a null value

My JavaScript code is causing some issues when executed with Selenium's JavascriptExecutor. Strangely, the code returns null through Selenium but a value in Firefox developer console. function temp(){ var attribute = jQuery(jQuery("[name='q& ...

Effective strategies for organizing component features in React

As I was reading through the React documentation, I came across the idea that using React effectively involves following the Single Responsibility Principle, meaning each component should have a specific purpose. I've already created a basic Gameboard ...

Alternating the tooltip icon based on the field's condition

Looking for a way to create a tooltip for an input field that involves changing icons based on certain conditions. An example scenario is the password field in a registration form. Seeking advice on the best approach to achieve this. Currently, here' ...

Insert a parameter or substitute the existing value if detected

Trying to create a JavaScript regex that searches for a parameter in a URL and replaces its value if found. If the parameter is not found, it should be added to the URL. Here are a couple of scenarios: http://www.domain.com/?paramZ=123456 https://www.dom ...

configure various search parameters simultaneously during the rendering process

Incorporating a Tree component from mui v5, I am aiming to include searchParams for the selected and expanded nodes. This task is accomplished using the useSearchParams hook from React Router (v6). The issue arises when both the selected and expanded even ...

The issue with ng-select arises when the placeholder option is selected, as it incorrectly sends "NULL" instead of an empty string

When searching for inventory, users have the option to refine their search using various criteria. If a user does not select any options, ng-select interprets this as "NULL," which causes an issue because the server expects an empty string in the GET reque ...

Creating pagination functionality for a React Material table

Check out this Spring Boot endpoint that I use for retrieving items from the database: import React, { useEffect, useState } from "react"; // Additional imports export default function BusinessCustomersTable() { // Functionality and code impl ...

What happens when 'grid' property is undefined in modal?

I encountered an issue with my modal where I wanted to display pre-selected rows, but kept getting a 'cannot read 'grid' of undefined' error. The UI Grids are defined within the modal, and I have declared two Grid APIs with different na ...

Using npm to trigger the package.json file will activate both the harp and browser-sync applications

I am looking for a way to simultaneously start a harp.js server and run a browser-sync process. This setup works perfectly on Linux with the following package.json configuration: { "scripts": { "dev": "bash ./serve.sh" } } Here is the content of ...

Connecting React.js with Socket.io for real-time communication and managing application

Hello, I am currently working on saving the response from my socket in a state via the backend. Here is a method where messages are sent to the socket: export default class Home extends Component { constructor(){ super() this.state ...

What could be causing Typescript Intellisense to not display Object extensions?

Let's take a look at this unique way to extend the Object type: interface Object { doSomething() : void; } Object.prototype.doSomething = function () { //perform some action here } With this modification, both of the following lines will c ...

The logic behind regular expressions

Currently working on building a web application with Angular 6 and I have a query: I'm in the process of developing a custom input component (specifically for text inputs) like so: @Component({ selector: 'input-text', templateUrl: &apos ...