Vue 3 with TypeScript: A Powerful Duo for Modern Development

Vue 3, the latest version of the popular JavaScript framework, combined with TypeScript, a statically typed superset of JavaScript, forms a formidable duo that brings modern development practices, enhanced developer experience, and improved code maintainability. In this article, we’ll explore the benefits of using Vue 3 with TypeScript, providing clear examples and insights into how this combination elevates your web development workflow.

Introduction to Vue 3 and TypeScript

What is Vue 3?

Vue 3 is a progressive JavaScript framework for building user interfaces. It is designed from the ground up to be more scalable, performant, and maintainable than its predecessor, Vue 2.

What is TypeScript?

TypeScript is a superset of JavaScript that adds static typing to the language. It helps catch errors during development, provides better tooling support, and improves code documentation.

Setting Up a Vue 3 Project with TypeScript

Vue CLI Installation

To create a new Vue 3 project with TypeScript, install Vue CLI globally:

npm install -g @vue/cli

Project Creation

Create a new project using the following command:

vue create my-vue-project

Choose the “Manually select features” option and enable TypeScript.

TypeScript in Vue Single File Components

Type Inference in Data and Methods

Vue 3’s TypeScript integration allows for excellent type inference in data and methods within single-file components.

// src/components/HelloWorld.vue
<template>
  <div>
    <h1>{{ greeting }}</h1>
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  data() {
    return {
      greeting: 'Hello, TypeScript!',
    };
  },
});
</script>

TypeScript in Vue Props

Strongly Typed Props

TypeScript enables strongly typed props, reducing runtime errors and improving code readability.

// src/components/UserProfile.vue
<template>
  <div>
    <h2>{{ user.name }}</h2>
    <p>{{ user.bio }}</p>
  </div>
</template>

<script lang="ts">
import { defineComponent, PropType } from 'vue';

interface User {
  name: string;
  bio: string;
}

export default defineComponent({
  props: {
    user: {
      type: Object as PropType<User>,
      required: true,
    },
  },
});
</script>

TypeScript in Vue Custom Directives

Typed Custom Directives

Define typed custom directives with TypeScript to ensure type safety.

// src/directives/focus.ts
import { App, DirectiveBinding } from 'vue';

const focusDirective = {
  mounted(el: HTMLElement) {
    el.focus();
  },
};

export default function install(app: App) {
  app.directive('focus', focusDirective);
}

TypeScript in Vuex for State Management

Typed Vuex Store

Use TypeScript interfaces to define the structure of your Vuex store for strong typing and improved tooling support.

// src/store/index.ts
import { createStore } from 'vuex';

interface AppState {
  user: {
    name: string;
    age: number;
  };
}

export default createStore<AppState>({
  state: {
    user: {
      name: 'John Doe',
      age: 25,
    },
  },
});

TypeScript in Vue 3 Lifecycle Hooks

Type Annotations for Lifecycle Hooks

Leverage TypeScript’s type annotations for more clarity in Vue 3’s lifecycle hooks.

// src/components/LifecycleDemo.vue
<template>
  <div>
    <p>Component mounted!</p>
  </div>
</template>

<script lang="ts">
import { defineComponent, onMounted } from 'vue';

export default defineComponent({
  setup() {
    onMounted(() => {
      console.log('Component mounted!');
    });
  },
});
</script>

TypeScript in Vue Router

Typed Vue Router

Take advantage of TypeScript to define typed routes and parameters in Vue Router.

// src/router/index.ts
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
import Home from '../views/Home.vue';

const routes: RouteRecordRaw[] = [
  {
    path: '/',
    name: 'Home',
    component: Home,
  },
  {
    path: '/about/:username',
    name: 'About',
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue'),
    props: (route) => ({ username: route.params.username }),
  },
];

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes,
});

export default router;

TypeScript in Vue 3 Plugins

Typed Vue Plugins

Create typed Vue plugins for better integration and type safety.

// src/plugins/myPlugin.ts
import { App } from 'vue';

interface MyPluginOptions {
  message: string;
}

const myPlugin = {
  install(app: App, options: MyPluginOptions) {
    console.log(options.message);
    // Additional plugin logic
  },
};

export default myPlugin;

TypeScript in Vue 3 Tests

Type-Safe Vue Test Utils

Leverage TypeScript for type-safe testing using Vue Test Utils.

// tests/unit/example.spec.ts
import { mount } from '@vue/test-utils';
import HelloWorld from '@/components/HelloWorld.vue';

describe('HelloWorld.vue', () => {
  it('renders props.msg when passed', () => {
    const msg = 'new message';
    const wrapper = mount(HelloWorld, {
      props: { msg },
    });
    expect(wrapper.text()).toMatch(msg);
  });
});

TypeScript with Vue 3 Composition API

Strongly Typed Composition Functions

Utilize TypeScript for strongly typed composition functions.

// src/composables/useCounter.ts
import { ref, computed } from 'vue';

export const useCounter = () => {
  const count = ref(0);

  const increment = () => {
    count.value++;
  };

  const doubledCount = computed(() => count.value * 2);

  return {
    count,
    increment,
    doubledCount,
  };
};

TypeScript in Vue 3 Dynamic Components

Typed Dynamic Components

Ensure type safety when working with dynamic components.

// src/components/DynamicComponent.vue
<template>
  <component :is="dynamicComponent" :data="dynamicData" />
</template>

<script lang="ts">
import { defineComponent, ref, PropType } from 'vue';

interface DynamicComponentProps {
  dynamicComponent: string;
  dynamicData: Record<string, unknown>;
}

export default defineComponent({
  props: {
    dynamicComponent: String as PropType<DynamicComponentProps['dynamicComponent']>,
    dynamicData: Object as PropType<DynamicComponentProps['dynamicData']>,
  },
});
</script>

TypeScript in Vue 3 with Class Components

Class Components with TypeScript

Use TypeScript in class-style components for a more structured approach.

// src/components/ClassComponent.vue
<template>
  <div>
    <h1>{{ greeting }}</h1>
  </div>
</template>

<script lang="ts">
import { Vue, Prop } from 'vue-property-decorator';

export default class ClassComponent extends Vue {
  @Prop(String) readonly name!: string;

  get greeting(): string {
    return `Hello, ${this.name}!`;
  }
}
</script>

Benefits of Vue 3 with TypeScript

Improved Developer Experience

TypeScript’s static typing provides autocompletion, better documentation, and early error detection, enhancing the overall developer experience.

Enhanced Code Maintainability

Strong typing reduces the likelihood of runtime errors, making code easier to maintain and refactor.

Conclusion: Elevating Vue 3 Development with TypeScript

Combining Vue 3 with TypeScript introduces a powerful synergy that modernizes your web development workflow. With strong typing, enhanced tooling support, and improved code maintainability, this duo sets the stage for building robust and scalable applications. Embrace Vue 3 and TypeScript to unlock a new level of efficiency and reliability in your modern web development projects. Happy coding!