踩坑:webstorm 中使用 typescript 自定义类型识别错误问题

6,986 阅读3分钟

问题描述

在前端项目中想使用 typescript 定义数据类型,但发现 webstorm 开发工具总是无法正确识别自定义的数据类型。如下图所示,points 类型已被定义为 Point[],但鼠标悬浮在 points 上,仍然显示为对象类型,其他自定义类型也出现同样的问题,不管自定义类型是定义在其他 .d.ts 类型声明文件中,还是同一份文件中,都出现同样的问题。

problem.png

问题排查

  1. 考虑到是 webstorm 出的问题,首先想到的是开发工具本身的问题,查找了很多互联网上资料,尝试更改 webstorm 的 typescript 相关配置,发现主要是在修改 typescript 依赖库地址和配置文件监视器,虽然不懂这些配置什么意思,但还是尝试修改下看看效果,最终发现修改这些配置后依然无法解决问题。

settings1.png

settings2.png

  1. 其次,想到是否有可能是项目依赖包引起的问题,尝试删除 node_modules,并重新 npm install,发现问题仍然得不到解决。

  2. 又想到是否因为 webstorm 缓存导致的问题,因此尝试清除缓存重启 webstorm,发现在重启后在建立索引前 .d.ts 文件的数据类型识别正确,但建立完索引后类型识别又变成了错误。

image.png

image.png

  1. 真是一个崩溃的过程。。。继续思考问题可能出在哪。依旧觉得还是 webstorm 本身出了问题,因为同样的 package.json 配置,其他项目没有遇到此问题,所以尝试删除 .idea 文件夹,重新构建项目,但问题依旧。。

  2. 最后,我尝试新建一个新的空项目不使用 npm 构建任何配置,直接把出错项目中的类型声明文件 .d.ts 文件拷贝到新项目中,类型识别没有问题。

image.png

由此,我确信是 typescript 本身出了问题,而我能接触到的只有 typescript 配置文件,即 tsconfig.json:

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "strict": true,
    "jsx": "preserve",
    "importHelpers": true,
    "moduleResolution": "node",
    "experimentalDecorators": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "sourceMap": true,
    "baseUrl": "./",
    "types": [
      "webpack-env",
      "jest"
    ],
    "paths": {
      "@/*": [
        "src/*"
      ]
    },
    "lib": [
      "esnext",
      "dom",
      "dom.iterable",
      "scripthost"
    ]
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
    "tests/**/*.ts",
    "tests/**/*.tsx"
  ],
  "exclude": [
    "./node_modules"
  ]
}

到底哪里出了问题呢?我百思不得其解,因为这份配置文件就是从我另一个没有出问题的项目中复制粘贴过来的,理论上不该有问题。为了探明配置中到底是哪项导致了问题的出现,我尝试把每一项注释掉来观察类型是否恢复正常,最终发现问题出在以下配置项。

"types": [
  "webpack-env",
  "jest"
]

通过查阅资料发现 types 的含义是 指定引入的类型声明文件,默认是自动引入所有声明文件,一旦指定该选项,则会禁用自动引入,改为只引入指定的类型声明文件,如果指定空数组[]则不引用任何文件。

问题总结

问题分析到这,基本已经明了了,导致问题的罪魁祸首就是 tsconfig.json 配置文件中的 types 配置项,项目中限定了 typescript 类型声明文件的引入类型,因此只要去掉此项(或者 types 数组中添加 "node")就可以正常引入所有的声明文件了。