Skip to main content
Vue 3 with Typescript and Decorators Reading time: 4 min

Vue 3 with Typescript and Decorators

Reading time: 4 min
Vue 3 with Typescript and Decorators

Always use TypeScript and decorator libraries in Vue projects when you prefer a class-style component syntax. In this guide we’ll build a simple counter component that can increment and decrement a value.

First, create a new project using the Vue CLI. If you don’t have it installed yet:

npm install -g @vue/cli

Create the project:

vue create vue-typescript-decorators

When prompted, choose “Manually select features” and enable TypeScript and Vuex (and Router if you need it).

Below are the relevant snippets used in the example. They are presented as fenced code blocks so the MDX parser treats them as code and doesn’t try to interpret Vue SFC markup inline.

<!-- src/views/Home.vue -->
<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png" />
    <Counter msg="Counter" />
    <HelloWorld msg="Welcome to Your Vue.js + TypeScript App" />
  </div>
</template>

<script lang="ts">
  import { Options, Vue } from 'vue-class-component'
  import HelloWorld from '@/components/HelloWorld.vue' // @ is an alias to /src
  import Counter from '@/components/Counter.vue'

  @Options({
    name: 'Home',
    components: {
      HelloWorld,
      Counter
    }
  })
  export default class Home extends Vue {}
</script>

Run the dev server:

npm run serve

Open the app at http://localhost:8080. Example source is available on GitHub: https://github.com/yacosta738/vue-typescript-decorators

// src/store/counter.ts
import { VuexModule, Module, Mutation, Action } from 'vuex-class-modules'

@Module({ generateMutationSetters: true })
export default class Counter extends VuexModule {
  // state
  private _count = 0

  // getters
  get count(): number {
    return this._count
  }

  // mutations
  @Mutation
  public addToCount() {
    ---
    title: Vue 3 with Typescript and Decorators
    description: Using TypeScript and decorator libraries with Vue to write class-style components. This article shows how to build a simple counter component.
    date: 2021-05-30T19:54:13.642Z
    cover: src/assets/images/vue3-typescript.webp
    author: en/yuniel-acosta
    tags:
      - en/vuejs
      - en/typescript
      - en/decorators
      - en/vuex
    category: en/software-development
    draft: false
    ---

    Always use TypeScript and decorator libraries in Vue projects when you prefer a class-style component syntax. In this guide we'll build a simple counter component that can increment and decrement a value.

    First, create a new project using the Vue CLI. If you don't have it installed yet:

    ```shell
    npm install -g @vue/cli

Create the project:

vue create vue-typescript-decorators

When prompted, choose “Manually select features” and enable TypeScript and Vuex (and Router if you need it).

Below are the relevant snippets used in the example. They are presented as fenced code blocks so the MDX parser treats them as code and doesn’t try to interpret Vue SFC markup inline.

<!-- src/views/Home.vue -->
<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png" />
    <Counter msg="Counter" />
    <HelloWorld msg="Welcome to Your Vue.js + TypeScript App" />
  </div>
</template>

<script lang="ts">
  import { Options, Vue } from 'vue-class-component'
  import HelloWorld from '@/components/HelloWorld.vue' // @ is an alias to /src
  import Counter from '@/components/Counter.vue'

  @Options({
    name: 'Home',
    components: {
      HelloWorld,
      Counter
    }
  })
  export default class Home extends Vue {}
</script>

Run the dev server:

npm run serve

Open the app at http://localhost:8080. Example source is available on GitHub: https://github.com/yacosta738/vue-typescript-decorators

// src/store/counter.ts
import { VuexModule, Module, Mutation, Action } from 'vuex-class-modules'

@Module({ generateMutationSetters: true })
export default class Counter extends VuexModule {
  // state
  private _count = 0

  // getters
  get count(): number {
    return this._count
  }

  // mutations
  @Mutation
  public addToCount() {
    this._count++
  }

  @Mutation
  public subtractFromCount() {
    if (this._count > 0) {
      this._count--
    }
  }

  // actions
  @Action
  public async add(): Promise<void> {
    this.addToCount()
  }

  @Action
  public async subtract(): Promise<void> {
    this.subtractFromCount()
  }
}

Register the module in src/store/index.ts:

import { createStore } from 'vuex'
import Counter from './counter'

const store = createStore({})

// tslint:disable-next-line:no-unused-expression
new Counter({ store, name: 'counter' })

export default store

The Counter component example (class-style with decorators):

<!-- src/components/Counter.vue -->
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <div>
      <button @click="add">+</button>
      <button @click="subtract">-</button>
    </div>
    <div>State: {{ counter }}</div>
    <div>Getter: {{ getCounter }}</div>
  </div>
</template>

<script lang="ts">
  import { Options, Vue } from 'vue-class-component'
  import { Prop } from 'vue-property-decorator'
  import { namespace } from 'vuex-class'

  const counterModule = namespace('counter')

  @Options({
    name: 'Counter'
  })
  export default class Counter extends Vue {
    @Prop({ type: String })
    private msg!: string

    @counterModule.State('_count')
    private counter!: number

    @counterModule.Getter('count')
    private getCounter!: () => number

    @counterModule.Action
    private add!: () => Promise<void>

    @counterModule.Action
    private subtract!: () => Promise<void>
  }
</script>

That’s it — run the project and visit the local address to see the counter demo.

Get started with AI today!

Join thousands of users leveraging AI to boost their productivity.

Comments

Loading comments...