How we integrated Typescript with Vue.js (2) at Infraspeak

Filipa Simão
infraspeak
Published in
6 min readSep 28, 2021

Infraspeak decided to migrate the application to improve code maintainability, performance, and UI/UX (learn more about it by reading “Incrementally migrating a legacy jQuery web application to a Vue.js SPA”, if you haven’t yet).

At that moment, we also made an important decision: to use Typescript. The main reason was that since our codebase uses Javascript, it’s harder to maintain. Without knowing the parameters and types of any object, the code is harder to understand and more error-prone.

After this decision, we needed to understand the best approach for us to integrate Typescript with Vue.js, since this framework offers us two big approaches to do it. That’s why I decided to wrote this article.

But first, let’s talk a little bit about Typescript.

What is Typescript?

Typescript, created by Microsoft, is an object-oriented programming language that extends from Javascript. This adds some new features to Javascript, like static typing, type annotations, and interfaces.

One advantage of using Typescript, as said before, is the type annotation. This means that we can add types into variables, function parameters, return values, and so on, using the:<type> keyword.

Sometimes it’s not necessary to specify a type, because Typescript can infer them automatically. For example, if we have a variable with an assigned value, the variable type will be the type of the assigned value.

Typescript provides us some default types like:string, number, boolean, Array, etc… but developers are free to extend and create new types.

Let’s take a look at how Typescript infers types:

If we reassigned the variable name to another type, an error is displayed:

It's also possible to add more than one type to a variable. This should be explicitly declared and cannot be inferred. This is called Union Type.

All the new functionalities that Typescript brings help us prevent some coding errors, because it gives us warnings before runtime (during development).

For example, if you have this code in Javascript:

This can be a problem because someone can add a string somewhere in the code.

With Typescript:

Note: It’s important to mention that browsers and node.js cannot execute Typescript, so it needs to be transpiled (converted) into Javascript.

Use Vue.js with Typescript

Vue.js supports Typescript so, as I said previously, we focused our decision on one of the two approaches we had for Vue.js:

  1. Use Vue.extend
  2. Use Class-based API

Vue.extend

This approach is the basic usage of Typescript. The Vue.extend allows the developers to have type annotation and inference. From both approaches this is the most similar to the Javascript version:

A disadvantage of this approach is the prop type. As you can see in the example above, we define the prop type this way:

Because, if we declare this way:

We will have an error ‘User’ only refers to a type, but is being used as a value here..

This happens because this definition will run during runtime execution, and this type does not exist when we transpile it to Javascript, unless it’s a primitive type. To avoid this, we must use PropType.

By using PropType, we send the Object type and declare it as the interface that we need.

Class-based API

This approach allows us to have a class-style syntax in our Vue Components. To work with this approach, the Vue Class Component package is mandatory.

It’s the approach that takes advantage of more features, such as:

  • Allows us to use ECMAScript features, like class inheritance, decorators, and other features in our Vue components.
  • Provides us decorators and custom decorators.
  • Allows us to add additional hooks for Vue Router.
  • We can also extend a Vue component class and use mixins.

These features make the components more maintainable and clear.

To get the most from using decorators - because Vue Class Component does not support all decorators by default - the Vue Property Decorators package is a good option, although it is not developed by the official Vue developers. This package adds more decorators like @Prop, @Watch, @Emit,and much more to our Vue component.

As we saw in the example above, we have:

  • readonly keyword in the user property: this means that this prop cannot be changed on this class or an error is triggered.
    Vue.js will also complain in runtime when trying to change a prop.
  • exclamation mark after user property: this means that Vue will initialise this property and is a non-null value because, in this case, it's required. If the prop was not required and does not have a default value, we need to use a question mark instead of the exclamation mark

Also, we did not have a problem assigning a type to props because the @Prop decorator already uses the PropType behind-the-scenes.

Decorators

Maybe for some people, decorators are an unknown term. The reason can be because in Javascript this feature is still a proposal, but in Typescript it’s already available. It’s not available by default, so it’s necessary to add "experimentalDecorators": true in tsconfig.json.

In Typescript, a decorator allows us to include the functionality of a function in the class declaration, class method, class accessor, class property, or class method parameter. They are identified for the prefixed at-sign (@) symbol.

In this example, we have two decorators: @Component and @Prop that are imported from Vue Property Decorators.

The@Component decorator, provided by Vue Class Component to Vue Property Decorators, is mandatory for building a component in Vue with the Class-based API approach because this decorator indicates the class is a Vue component.

If it’s necessary to import and register another’s components, we use that decorator:

The advantage of using decorators is that it allows us to have a cleaner code and reuse the same decorator as many times as we want.

Is also possible to use Typescript and decorators in Vuex. One way is using the package Vuex Class Modules. This allows us to use @Module, @Mutation, and @Action decorators.

This is the approach that we use at Infraspeak.

Conclusion

The decision to use Vue.js and Typescript with decorators is definitively responding to our main needs at Infraspeak. Fortunately, some of our colleagues were already familiarised with using class API and decorators, which helped us integrate this new approach faster, resulting in a much cleaner and readable codebase.

Using Typescript in large codebases, or even in small projects, can be a powerful tool, since it can be extra helpful for developers to create maintainable and scalable projects, with a stronger architecture and patterns.

We have a plan in our roadmap to migrate our current architecture from Vue 2 to Vue 3, which has built-in Typescript. But first, we need to be sure that Vue 3 fully supports the packages that we are currently using and plan to make a refactor to split our project into smaller packages to have a smooth integration and validation of Vue 3.

For more information and details, please visit Typescript and Vue Docs… and stay tuned on our blog posts!

--

--