Building VueJS Applications with TypeScript

George Hanson on September 10, 2018

TypeScript has undoubtedly grown in popularity over recent years. More and more developers within the web industry are looking to use static-type... [Read Full]
markdown guide

Glad I'm not the only one that likes separating template files.

Good to know about the use of a decorator to load in the template file - might give it a try and see what I prefer.

I've been using the below to load in my template files.

    template: require('./template.html'),
export default class LinkComponent extends AbstractBEMComponent

Alternatively I've also been using the below:

import template from './template.html';

export default class LinkComponent extends AbstractBEMComponent

The second requires the below to be added to .d.ts file as mentioned in your post.

declare module "*.html" 

That's how I used to do it before, which in my opinion works pretty well. I just prefer the use of the decorator


Fair enough - I wasn't sure if it was missing out any magic behind the scenes as I'm not using vue-template-loader. :)


can you provide me gihub link please because it is not working on mine it says
You may need an appropriate loader to handle this file type. while compiling can anyone give me idea


Awesome article George!

If I created another component in your project above, call it "CustomComponent", how could I reference it from within the html template of hello-world.html? In other words, I'd like to add something like:

<CustomComponent />

inside of hello-world.html. How could I do that? I know you mentioned you'd write an article in the future that would mention child components, but I'd really like to learn how to do that ASAP because your article has inspired my team to try your approach immediately but I'm stuck on this question.

Thanks again for the excellent article,



Keep checking back, I'm working on something soon! :)

In response to your question, you can do something like this:

import { Component, Vue } from 'vue-property-decorator';
import WithRender from './hello-world.html';
import CustomComponent from './CustomComponent.ts';

    components: {
export default class HelloWorld extends Vue {

That would then make it available for use within that particular component.


Hey George Hanson,

nice article. But now, I have two questions:

  • what about the styles? How do you write the css(scss/whatever) for your typescript components? And in particular, did you manage to have the styles scoped to the component?
  • Would you care to elaborate on the benefits of writing your components in 2/3 files instead of the one file approach? I am personally conflicted about that. I researched this topic, but could not find any strong argument. Most of it is about liking one approach more.

Hi there,

I generally prefer to keep styling away from these components and instead have SCSS files which are compiled separately. The reason I prefer this is that I'm not a massive fan of styles being dynamically injected into the page. But that's more of a personal preference.

With this approach, you write two files per component instead of one per component. Now this is mainly down to personal preference but here is why I like it. Some components can start to have more complicated logic and when you choose to start having service classes, models and follow design patterns it becomes harder to do within just one file. Everything starts to get messy and it can be difficult to read.


Thank you for your reply. I'll think about it

For your information, unless I am wrong, it looks like the build process of vue-cli 3 builds a css file, which is not dynamically injected. However, I think that it was not like that before, not sure though.


I had learnt Angular first and am now building an application in Vue. When planning the architecture of the application, I was wanting to separate the HTML, TS and SCSS following the same convention as Angular.

However I've since reverted back to single-file-components because I am yet to find an IDE (IntelliJ, VSCode) which can lint files when separated and recognise custom components in HTML.

Are you experiencing the same problems and have you overcome them?


Hi, this is very very very informative. I would just like to ask about the difference in separating template to another file rather than just using Vue file? you know something like pros and cons, or is this just something like developer-preferences? Thanks :D


Hi there,

I'm glad you found it informative:)

In answer to your question, it really is all developer preference. One reason I prefer it is when using class style components it can get a bit messy IMO with the template in the same file.

So if you want to use .vue files then feel free, it is entirely up to you :)


Hi George, Just following your article and thanks for posting it's really getting me started with TS & Vue and separating out the markup. I'm just having a slight error when building and running, I'm sure I must have missed something but can't see what it could be, I was wondering if you or one of your readers might have a suggestion.
I needed to remove some of the HTML formatting from the snippet below to get this post to pass.

Kind Regards
The error is
error in ./src/components/hello-world.html

Module parse failed: Unexpected token 1:0
You may need an appropriate loader to handle this file type.
div class="hello"
h1 msg /h1


Great article !!!

I'm starting with typescript, but I like the angular approach to initializing components.

Overloading @component to have templateUrl would be cool.
Or in your example, rather have an @template('./url') decorator;
I find it clearer than importing a withRender and directly doing @withRender.

However, how to manage scss files in the same way?


Thanks for this. I externalized my Navbar, but the image used will now no longer load. I've tried just about every path under the sun ./assets, ../assets, ../../assets, ../../../assets, the @assets or ~assets or ~@assets and just seems something with the external "WithRender" maybe isn't getting picked up by Webpack (vue.config.js) now.
Any one else have this issue? I'm all but left with jamming it into SCSS now to just workaround it.


There are only two screenshots. Neither of which you need to read the contents of or pay much attention to.


Hi George,

Thanks for the article.

The first screenshot for vue project creation shows Babel unticked, the second screenshot shows selecting Yes to using Babel alongside TS.


sorry. how can we add an external css/scss file to component?


If we haven't .vue files (only .ts with imported .html template), how to test it with jest & @vue/test-utils?

code of conduct - report abuse