npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

types-vue

v1.1.0

Published

Vue typescript decorators

Downloads

293

Readme

types-vue

Binding helpers for Vuex and vue-class-component on steroids

Dependencies

Based on

Installation

$ npm install --save types-vue
# or
$ yarn add types-vue

Usage

There are these decorators for a component:

  • Component (from 'vue-class-component')
  • Prop
  • Watch
  • MapGetter
  • MapAction

And these decorators for a vuex module:

  • Module
  • Getter
  • Mutation
  • Action

Component

@Prop

This decorator adds the field to "props" component collection. It can be invoked in different ways:

  1. Without parameters
  2. With the type constructor (ex. Number, String, Boolean...)
  3. With PropOptions:
    • type: type constructor (ex. Number, String, Boolean...)
    • required: boolean
    • default: defaul value of the prop
    • validator: a validator function
import { Vue, Component, Prop } from 'types-vue';

@Component
export default class MyComponent extends Vue {
    @Prop()
    title!: string;

    @Prop(Number)
    count!: number;

    @Prop({
        type: String,
        required: false,
        default: '[email protected]',
        validator(value: string): boolean {
            return true;
        }
    })
    email!: string;
}

This is like:

export default {
  props: {
    title: { },
    count: Number,
    email: {
        type: String,
        required: false,
        default: '[email protected]',
        validator(value: string): boolean {
            return true;
        }
    },
  }
}

@Watch

This decorator adds the method to "watch" component collection. It can be invoked in different ways:

  1. With the name of the property to watch.
  2. With the name of the property to watch and WatchOptions:
    • deep: boolean
    • inmediate: boolean
import { Vue, Component, Watch } from 'types-vue';

@Component
export default class MyComponent extends Vue {
    title: string = 'hello';
    counter: number = 0;

    @Watch('title')
    onTitleChanged(value: string): void {
        console.log('title is ' + value);
    }

    @Watch('counter', { deep: true, immediate: true })
    onCounterChanged(value: number, oldValue: number): void {
        console.log('counter is ' + value.toString());
    }
}

This is like:

export default {
    data() {
        return {
            title: 'hello',
            counter: 0
        };
    }
    watch: {
        'title': {
            handler: 'onTitleChanged',
            immediate: false,
            deep: false
        },
        'counter': {
            handler: 'onCounterChanged',
            immediate: true,
            deep: true
        }
    },
    methods: {
        onTitleChanged(value) {  
            console.log('title is ' + value);
        },
        onCounterChanged(value, oldValue) {
            console.log('counter is ' + value.toString());
        }
    }
  }
}

@Filter

This decorator adds the method to "filters" component collection.

import { Vue, Component, Watch } from 'types-vue';

@Component
export default class MyComponent extends Vue {

    @Filter()
    static withExclamation(value: string): string {
        return '!' + value;
    }
}

This is like:

export default {
    filters: {
        withExclamation(value) {  
            return '!' + value;
        }
    }
  }
}

@MapGetter

When you are using Vuex, this decorator adds the field to "computed" as a vuex mapGetter in the component. It can be invoked in different ways:

  1. Without parameters
  2. With MapGetterOptions:
    • namespace: the name of the module namespace
import { Vue, Component, MapGetter } from 'types-vue';

@Component
export default class MyComponent extends Vue {
    @MapGetter()
    title: string;

    @MapGetter({ namespace: 'counter' })
    count: number;
}

This is like:

export default {
  computed: {
    ...mapGetters(['title']),
    ...mapGetters('counter', ['count'])
  }
}

@MapAction

When you are using Vuex, this decorator adds the field to "methods" as a vuex mapAction in the component. It can be invoked in different ways:

  1. Without parameters
  2. With MapActionOptions:
    • namespace: the name of the module namespace
import { Vue, Component, MapAction } from 'types-vue';

@Component
export default class MyComponent extends Vue {
    @MapAction()
    changeTitle: any;

    @MapAction({ namespace: 'counter' })
    increment: (val: number) => void;
}

This is like:

export default {
  methods: {
    ...mapActtions(['changeTitle']),
    ...mapActtions('counter', ['increment'])
  }
}

Vuex Module

@Module

If you are using Vuex, and you want to create a new module, you can use the Module decorator and extends the VuexModule class. You can call the Module decorator:

  1. Without parameters
  2. With ModuleOptions:
    • name: the namespace name of the module;
    • namespaced: a boolean value to set if you are going to use namespacing in this vuex module;
import { Module, VuexModule } from 'types-vue';

@Module({ namespaced: true })
export default class extends VuexModule {
    counter: number = 0;
}

This is like:

export default {
  namespaced: true,
  state: {
      counter: 0
  }
}

@Getter

This decorator adds the method to "getters" vuex module collection.

import { Module, VuexModule, Getter } from 'types-vue';

@Module({ namespaced: true })
export default class extends VuexModule {
    _counter: number = 0;

    @Getter()
    counter(): number {
        return this._counter;
    }
}

This is like:

export default {
  namespaced: true,
  state: {
      _counter: 0
  },
  getters: {
      counter: function(state) {
          return state._counter;
      }
  }
}

You can determine the access mode to the vuex store Getter:

import { Module, VuexModule, Getter } from 'types-vue';

@Module({ namespaced: true })
export default class extends VuexModule {
    _list: string[] = []];

    @Getter({ mode: 'value'})
    listValue(): string[] {
        return this._list;
    }

    @Getter({ mode: 'reference'})
    listReference(): string[] {
        return this._list;
    }
}

This is like:

export default {
  namespaced: true,
  state: {
      _counter: 0
  },
  getters: {
      listValue: function(state) {
          return state._list;
      },
      listReference: function(state) {
          return Object.assign({}, state._list);
      }
  }
}

@Mutation

This decorator adds the method to "mutations" vuex module collection.

import { Module, VuexModule, Mutation } from 'types-vue';

@Module({ namespaced: true })
export default class extends VuexModule {
    _counter: number = 0;

    @Mutation()
    increment(value: number): void {
        this._counter += value;
    }
}

This is like:

export default {
  namespaced: true,
  state: {
      _counter: 0
  },
  mutations: {
      increment: function(state, value) {
          state._counter += value;
      }
  }
}

@Action

This decorator adds the method to "actions" vuex module collection.

import { Module, VuexModule, Mutation, Action } from 'types-vue';

@Module({ namespaced: true })
export default class extends VuexModule {
    _counter: number = 0;

    @Mutation()
    increment(value: number): void {
        this._counter += value;
    }

    @Mutation()
    decrement(value: number): void {
        this._counter -= value;
    }

    @Action({ commit: 'increment' })
    incr(value: number): number {
        if (value < 0) {
            return 0;
        }

        return value;
    }

    @Action({ useContext: true })
    decr(context: ActionContext<any, any>, value: number): void {
        if (value < 0) {
            return 0;
        }

        context.commit('decrement', value);
    }
}

This is like:

export default {
  namespaced: true,
  state: {
      _counter: 0
  },
  mutations: {
      increment: function(state, value) {
          state._counter += value;
      },
      decrement: function(state, value) {
          state._counter += value;
      }
  },
  actions: {
      incr: function(context, value) {
          let result = (value) => {
                if (value < 0) {
                    return 0;
                }

                return value;
          }();
          context.commit('increment', result);
      },
      decr: function(context, value) {
          let result = (value) => {
                if (value < 0) {
                    return 0;
                }

                return value;
          }();
          context.commit('decrement', result);
      }
  }
}

Examples

You can see a complete demo project in the demo folder of this project. The code is like the following:

Component

// header-panel.ts
import { Vue, Component, Prop, Watch } from 'types-vue';

@Component
export default class Header extends Vue {
    @Prop()
    title!: string;

    @Watch('title')
    onTitleChanged(value: string) {
        console.log('title is ' + value);
    }
}
<!-- header-panel.vue -->
<template>
    <div>
        <h1>{{ title }}</h1>
    </div>
</template>
<script src="./header-panel.ts"></script>
// demo.ts
import { Vue, Component, Watch } from 'types-vue';
import HeaderPanel from './header-panel.vue';

@Component({
    components: {
        'header-panel': HeaderPanel
    }
})
export default class NotificationPanelComponent extends Vue {
    title: string = 'Hello Vue from typescript';

    @Watch('title')
    onTitleChanged(value: string) {
        console.log('in demo the title is ' + value);
    }
}
<!-- demo.vue -->
<template>
    <div>
        <header-panel :title="title" :kk="title" />
        <p>
            <span>Change the title:</span>
            <input type="text" v-model="title" />
        </p>
    </div>
</template>
<script src="./demo.ts"></script>

Vuex

// counterModule.ts
import { Module, VuexModule, Mutation, Action, Getter } from 'types-vue';

@Module({ namespaced: true })
export default class extends VuexModule {
    _counter: number = 0;

    @Getter()
    counter(): number {
        return this._counter;
    }

    @Mutation()
    increment(value: number): void {
        this._counter += value;
    }

    @Mutation()
    decrement(value: number): void {
        this._counter -= value;
    }

    @Action({ commit: 'increment' })
    incr(value: number): number {
        if (value < 0) {
            return 0;
        }

        return value;
    }

    @Action({ commit: 'decrement' })
    decr(value: number): number {
        if (value < 0) {
            return 0;
        }

        return value;
    }
}
// store.ts
import Vue from 'vue';
import Vuex, { Store } from 'vuex';
import counter from './counterModule';

Vue.use(Vuex);

const store = new Store({
    state: {},
    modules: {
        counter
    }
});

export default store;
// counter-panel.ts
import { Vue, Component, MapGetter, MapAction } from 'types-vue';

@Component
export default class NotificationPanelComponent extends Vue {
    @MapGetter({ namespace: 'counter' })
    counter;

    @MapAction({ namespace: 'counter' })
    incr;
}
<!-- counter-panel.ts -->
<template>
    <div>
        <p>The counter is {{ counter }}</p>
        <button v-on:click="incr(1)">Add 1</button>
    </div>
</template>
<script src="./counter-panel.ts"></script>

License

MIT