Writing Single File Components (Vue Files) in Typescript: vue-class-component vs. Vue.extend

Mitchell Garcia
Front-End Society
Published in
3 min readJan 16, 2018

UPDATE:

This article was written in early 2018. Since is was written, Vue 2.6 was released, and the PR is merged! This article is out of date and I will write an update shortly.

If you come from Typescript, the first thing you’re looking for when picking up Vue is making sure your Vue files are type-safe.

While simply adding lang="ts" to your script tag in your .vue file and writing components like normal technically works, you’re missing out on basically 90% of the tooling Typescript offers.

This article will go over the two recommended ways of writing Vue components in Typescript, both of which are supported in the Vue documentation.

vue-class-component

vue-class-component is a ES / Typescript decorator that provides users with the abiliity to write class-style Vue components. It is usually used in conjunction with the vue-property-decorator.

Here is an example of a component written using vue-class-component:

Example of using vue-class-component

The class will be mapped to a Vue component using the below blueprint:

  • Data → any property on the class that is defined and instantiated
  • Computed Properties → getters
  • Methods → any property on the class that is a function
  • Props → any property defined as a prop using the @prop() decorator or as an argument to the @component() decorator (example here)

Until recently, this has been the only way to get type-safety in your Vue components.

Vue.extend()

The latest release of Vue rewrote some parts of the Typescript architecture, and we have a new way to write Vue components in Typescript: Vue.extend.

I call this the classic method, because it’s literally the same exact thing as a standard Vue component, only it must be explicitly wrapped in Vue.extend.

Thanks to the latest changes and type-inference, the Typescript compiler can now automatically provide typings for your Vue components based on the object structure you provide as an argument in Vue.extend()

Example of defining a Vue component using Vue.extend

One important distinction between this and vue-class-components is that these are not classes, but basic objects.

Additionally, because this is the classic way of defining Vue components, all standard Vue tooling works out of the box (like Vetur).

Vetur intellisense for component definitions

But Which One Is Better?

Comparison of the two methods

While reading keep in mind: these are just style differences that achieve almost the same thing.

I personally prefer Vue.extend because I believe it’s easier to teach and reason about. Stylistically, it’s more like putting Typescript-in-Vue, as opposed to putting Vue-in-Typescript.

The additional layer of abstraction is not worth the convenience, especially with typed-props coming soon.

vue-class-component might make more sense if you have complex props that require custom typings. At the current version, it’s impossible to implicitly cast a prop to a class/interface using Vue.extend.

At the moment, both of these are included in the official documentation, so both will be supported.

Thanks for reading Front End Society! Follow me on Twitter: mmitchellgarcia

--

--