背景

为了跟上前端技术的潮流,我在新项目中使用了 TypeScript 。刚开始开发的时候,遇到了一些令我一头雾水的 bug,现在整理出来,让大家和我一起避免重复踩雷。

遇到的问题

1. 在 ts 中引入 .vue 文件会报错

Cannot find module '@/components/loading-bar'.

由于 TypeScript 默认并不支持 *.vue 后缀的文件,所以在 vue 项目中引入的时候需要创建一个 vue-shim.d.ts 文件,放在项目项目对应使用目录下,例如 src/vue-shim.d.ts

// 如果使用 vue-cli3 的话,这个文件应该会被自动创建
declare module "*.vue" {
  import Vue from "vue";

  export default Vue;
}

意思是告诉 TypeScript*.vue 为后缀的文件可以交给 vue 模块来处理。

而在代码中导入 *.vue 文件的时候,需要写上 .vue 后缀。原因还是因为 TypeScript 默认只识别 *.ts 文件,不识别 *.vue 文件。

解决办法: 引入的时候加上 .vue 后缀

2. 在 ts 中使用 webpack 中配置的 alias 会报错

解决办法:在 tsconfig.json 中进行配置:

"compilerOptions": {
        // ...
    "paths": {
      "@/*": ["src/*"],
      "@components/*": ["src/components/*"],
      "@views/*": ["src/views/*"]
    }
  },

3. 在 ts 中引入外部模块有时会报错,例如

import JsCookie from 'js-cookie';

部分 npm 包没有 index.d.ts 文件,因此直接 import 可能出错。

解决办法:

  • 可以使用 require 例如在文件中引入
const moment = require('moment');
  • 或者直接install它的ts库例如
npm i --save-dev @types/moment

4. vuex 与 typescript 支持度很差,直接使用 mapState 不起作用

解决办法:使用 vuex-class 包进行替代。

import { State } from 'vuex-class';

//...
@State myState!: string

5. 使用 element-ui 之后,this.$message 会报错

Property '$message' does not exist on type 'App'.

编译时默认拉取node_modules/@types下面的文件,额外还有typeRootstypes两个属性可以自定义配置 看下我们项目中的tsconfig文件:

{
    "compilerOptions": {
        "types": [
             "webpack-env",
             "jest"
        ]
    }
}

设置了 types 属性,表示只使用以下位置的配置:

node_modules/@types/webpack-env

node_modules/@types/chai

但是 element-ui 的types位置在 node_modules/elememt-ui/types 下面,所以将这个位置加入了配置中:

{
    "compilerOptions": {
        "types": [
            "webpack-env",
            "jest",
            "./../element-ui/types"
        ]
    }
}

即可编译成功!