[Vuejs]-Wrapping Vue computed properties and methods while preserving type signature on Vue.extend constructor

0👍

While typing up the example component for this, I managed to achieve what I wanted: A single method that wraps Vue.extend while hooking in a chronometer on certain 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);
}

Simple call wrap({...componentOptions}) rather than Vue.extend({...componentOptions}) and it will hook the chronometer.

$options doesn’t play too nice, but being a little sneaky seems to suppress errors

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

Leave a comment