DEV Community

Cover image for Integrate TypeScript in your Vue project
Alex Jover
Alex Jover

Posted on • Originally published at alexjoverm.github.io

Integrate TypeScript in your Vue project

You have a Vue project and you heard about all things TypeScript can help you with. You decide to start using TypeScript. Here you'll see how to do that in an approachable and pragmatic way.

In this article we'll assume you're using SFC (Single File Components), but it could work as well even if you're splitting them into multiple files. So... let's get started!

Integrating TypeScript

We're gonna start from Vue CLI Webpack's template, but it would work as well with the amazing PWA template. Don't choose to use ESLint when you're ask to:

vue init webpack my-app # or: vue init pwa my-app
cd my-app
Enter fullscreen mode Exit fullscreen mode

We have to do 4 steps:

1. Create a tsconfig.json file

Let's start with something very simple, later we'll get back to the TypeScript configuration.

{
  "compilerOptions": {
    "lib": ["dom", "es5", "es2015"],
    "target": "es5",
    "module": "es2015",
    "moduleResolution": "node",
    "sourceMap": true,
    "allowSyntheticDefaultImports": true
  }
}
Enter fullscreen mode Exit fullscreen mode

The most important part is the allowSyntheticDefaultImports setting. Since Vue types doesn't use ES2015 default exports, this setting must be set to by-pass that. You can see more info in this VSCode docs page.

Setting "module": "es2015" would make the code tree-shakeable by producing ESM (EcmaScript Modules).

2. Add ts-loader and webpack tweaks

Install typescript an ts-loader with npm:

npm i -D typescript ts-loader
Enter fullscreen mode Exit fullscreen mode

Then open build/webpack.base.conf.js, and place the following code at the beginning of module.rules, right before than vue-loader:

module: {
    rules: [
      {
        test: /\.ts$/,
        exclude: /node_modules|vue\/src/,
        loader: "ts-loader",
        options: {
          appendTsSuffixTo: [/\.vue$/]
        }
      },
    ...
Enter fullscreen mode Exit fullscreen mode

In there, rename the entry to .ts and add it to the extensions:

...
entry: {
  app: './src/main.ts'
},
...
resolve: {
    extensions: ['.ts', '.js', '.vue', '.json'],
...
Enter fullscreen mode Exit fullscreen mode

3. Add es-module: true to build/vue-loader.conf.js

That will tell vue-loader to use ES instead of CJS (CommonJS) modules, as describe in vue-loader docs:

module.exports = {
  loaders: utils.cssLoaders({
    sourceMap: isProduction
      ? config.build.productionSourceMap
      : config.dev.cssSourceMap,
    extract: isProduction
  }),
  esModule: true
}
Enter fullscreen mode Exit fullscreen mode

4. Use TypeScript in files

So you must do 2 things here:

  • Rename .js to .ts extensions within the src folder
  • Use lang="ts" on the script tag of you Vue file. For example in App.vue:
<script lang="ts">
export default {
  name: 'app'
}
</script>
Enter fullscreen mode Exit fullscreen mode

Troubleshooting

If your editor is yelling at the line import App from './App' in main.js file about not finding the App module, you can add a vue-shim.d.ts file to your project with the following content:

declare module "*.vue" {
  import Vue from 'vue'
  export default Vue
}
Enter fullscreen mode Exit fullscreen mode

I'm using VSCode 1.13.1 and not seeing it, but I've seen it before.

TSLint, Prettier... Goddess!

I've recorded a 2 min video on Egghead where I explain how you can set up TSLint with Prettier without any conflicts. Go check it out!

Ok, I can use TypeScript... so now what's next?

At this point, TypeScript could already point you out to some errors you haven't noticed before by using built-in and third-party types and gives you a better dev experience by using type inference, as explained in TypeScript at Slack, an article telling how Slack moved their codebase to TypeScript.

Still, you must add your own types by using interfaces, types, enums, classes and whatever you need. That way you'll add more type coverage that TypeScript will use to apply static typing, assuring type safety.

Ideally, you'd use the TypeScript 2.3 strict compiler option in your tsconfig.json because it'll bring you the most type safety. Marius Schulz has a well explained article about this. By TypeScript 2.3, the strict option is a group of 4 options, but in future releases it could add more:

  • strictNullChecks
  • noImplicitAny
  • noImplicitThis
  • alwaysStrict

However, if you have a medium/large codebase, using strict option will make you spend really a huge effort and time solving all the type shortage.

For that case, a good way to integrate TypeScript is to start with the most flexible configuration, and as you add more type coverage to your codebase, start to enable individually the flags mentioned above, till you get to the point that you can apply the strict option, so you can approach it in a pragmatic way.

Conclusion

TypeScript brings you type safety to your codebase from the very start, but the more types you define, the more easy to detect bugs and errors and to make the code maintainable. Vue from version 2 is shipped with typings, so we can make use of them. They become more powerful when you use OOP (Object Oriented Programming) in Vue, but will see that in another post.

If you like it, please go and share it! You can follow me on this blog or on twitter as @alexjoverm. Any questions? Shoot!


Originally posted at alexjoverm.github.io on June 28, 2017

Top comments (2)

Collapse
 
galdin profile image
Galdin Raphael

Thanks for this! Had to do this recently. I followed the readme from Microsoft's TypeScript Vue Starter and I was good to go.

Collapse
 
alexjoverm profile image
Alex Jover

Yes, that's a good example as well, maybe a bit extensive. In this post I wanted to show how to do it using the vue-cli webpack and pwa template, since have much more production ready features and lots of projects are based on them. Also to describe how to do it with projects already done with those templates, in a pragmatic way.

Glad you liked it!