Vue2.5+ Typescript introduces a comprehensive guide

Writing in the front

At the time of writing this article, I’ve been using Vue for over three months, Typescript is completely blank, and I’ve spent about three nights migrating my projects to Typescript, so this article is more of a guide to getting started.

General principles

Two principles:

Minimum dependency introduction

Since my personal upgrade from Javascript to Typescript tends to be smooth and smooth, I’m generally restrained in introducing new dependencies, only introducing what’s necessary to keep it as close to native VUE writing as possible:

  • typescript
  • ts-loader

None of the following dependencies are introduced:

  • vue-class-component: official maintenance, learning cost is small, but withvuexIntegration is very poor, the plan and other official perfectionvuexSupport it before introducing it
  • vue-property-decorator: Unofficial maintenance, certain learning costs
  • vuex-class: unofficial maintenance, supplemented by vue-class-ComponentvuexSupport (limited support)
  • vuex-ts-decorators/vuex-typescriptEtc. : Unofficial maintenance, high learning costs

PS: To summarize, it is necessary to introduce the vue-class-Component maintained by vUE.

PS: tslint-loader is optional as vUE support is not perfect and is explained at the end of this article.

Since you use Typescript, don’t use any unless you have to!

Any is like a Pandora’s box. Once you open it, you can easily get into the habit of being lazy. My advice, therefore, is to try not to touch it unless you have nowhere else to turn.

Vue-cli generated projects enable Typescript

Note: This is only for use with Webpack templates.

Vue init Webpack < project name > generates projects with the following changes to be Typescript compatible:

Depend on the installation

NPM I — Save typescript TS-loader install necessary dependencies. CNPM is recommended.

Webpack configuration

. / build/webpack. Base. Conf., js, the following changes:

  • Entry entry filemain.jsInstead ofmain.ts:
entry: {
  app: './src/main.ts'
}Copy the code
  • resolve.extensionsadd.ts:
resolve: {
  extensions: ['.js', '.ts', '.vue', '.json']
}Copy the code
  • module.rulesadd.tsParsing rules:
module: {
  rules: [
    {
      test: /\.tsx?$/,
      loader: 'ts-loader',
      exclude: /node_modules/,
      options: {
        appendTsSuffixTo: [/\.vue$/]
      }
    }
  ]
}Copy the code

tsconfig.json

Add the tsconfig.json file to the root path of the project. The recommended configuration is as follows:

Json {"compilerOptions": {// conform to Vue's browser support "target": "es5", // this allows stricter inferences on data attributes on 'this' : True, // If using webpack 2+ or rollup, use tree-shake: "module": "es2015", "moduleResolution": "node"}}Copy the code

vue-shim.d.ts

Add file vue-shim.d.ts to SRC directory:

declare module "*.vue" {
  import Vue from "vue";
  export default Vue;
}Copy the code

This tells TypeScript *. Vue files to be processed by the vue module.

Js files are renamed to.ts files

Js from SRC /main.js, including SRC /router/index.js

Note: after renaming the import of vue files, add the. Vue suffix

Because Typescript only recognizes *. Ts files by default, not *. Vue files

Before:

import App from './App'
import HelloWorld from '@/components/HelloWorld'Copy the code

Should be changed to:

import App from './App.vue'
import HelloWorld from '@/components/HelloWorld.vue'Copy the code

Vue file modification

Key points:

  • <script>addlang="ts"The statement
  • useVue.extendDefine the components

Example:

// src/components/HelloWorld.vue
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  }
})
</script>Copy the code

npm run dev

At this point, the project is ready to run, and vue’s initial introduction of typescript is complete.

TSLint

Currently (as of November 2017), you can enable build-time TSLint support for.vue files without turning off no-avatar-blank-lines; As for the VSCode editor’s edit-time prompt, none at all.

See TSLint’s issue and Vetur’s issue for details

Unfortunately, I can’t take it eitherESLintMake do, or a bunch of errors like this await you:

So, you’re left with two options, either turn it off or make do with it:

  • Add the dependent
npm i --save-dev tslint tslint-loader tslint-config-standardCopy the code
  • module.rulesremoveeslint-loaderTo addtslint-loaderpretreatment
// ./build/webpack.base.conf.js
module: {
  rules: [
    // {
    //   test: /\.(js|vue)$/,
    //   enforce: 'pre',
    //   exclude: /node_modules/,
    //   use: {
    //     loader: 'eslint-loader',
    //     options: {
    //       formatter: require('eslint-friendly-formatter')
    //     }
    //   }
    // },
    {
      test: /\.ts$/,
      exclude: /node_modules/,
      enforce: 'pre',
      loader: 'tslint-loader'
    },
    {
      test: /\.vue$/,
      loader: 'vue-loader',
      options: vueLoaderConfig
    },
  ]
}Copy the code
  • vue-loaderIn the opentslint-loaderOptions:
// ./build/vue-loader.conf.js const merge = require('webpack-merge') module.exports = { loaders: merge(utils.cssLoaders({ sourceMap: isProduction ? config.build.productionSourceMap : config.dev.cssSourceMap, extract: isProduction }), { ts: ['ts-loader', 'tslint-loader'] } ), ... // Other content}Copy the code
  • Add files under the project root pathtslint.json:
// tslint.json
{
  "extends": "tslint-config-standard",
  "globals": {
    "require": true
  },
  "rules": {
    "no-consecutive-blank-lines": false
  }
}Copy the code

The closure of no-avatar-blank-lines is explained here

Using vue-loader with tslint-loader is like leaving all non-JS contents such as

Rerun thenpm run devTo see what might be output at build timeeslintWarning (esLint defaults to warning and does not block builds, error can be changed if needed)

The necessity of vue-class-Component

The native VUE component writing leads to a vexing problem:

Data () is inferred to be of type []never if it defines an array as follows:

export default Vue.extend({
  data () {
    return {
      list: []  // type: []never
    }
  }
})Copy the code

In this case, the array is nullified because it cannot add value to the array.

export default Vue.extend({
  data () {
    const list: string[] = []
    return {
      list: list
    }
  }
})Copy the code

Vue-class-component class = component class = component class = component class

<script lang="ts">
import Vue from 'vue'
import Component from 'vue-class-component'

@Component
export default class HelloWorld extends Vue {
  list: string[] = []

  hello () {
    list.push('Hello world')
  }
}
</script>Copy the code

I personally consider that vue-class-Component has poor support for vuex mapState, mapGetters and other functions (can be referenced by vuex-class). Adding Decorators isn’t my core typescript requirement (interfaces are!). , the decision to defer the introduction, not to add complexity.

Vuex

It needs to be added.