Appearance
前言
最近vscode总是类型检查报各种奇怪的错误,严重不符合预期。重新研究下这块的配置。想起什么写什么,这块场景比较多,别名叠加monorepo后更是难以理解,里面的坑特别多。
npx 执行方式
从当前目录向上一直查询node_module/.bin 查询命令。如果查询不到则下载命令到一个tmp。执行tmp中命令,执行后删除。
什么是tsc根目录
当tsc 不指定tsconfig.json 运行时,默认查找当前执行目录最近的tsconfig.json
- tsc运行时的目录 (不是)
- tsconfig.json 所在的目录 (正确)
- tsconfig.json中baseUrl 指的目录。(不是)
types 和 typeRoots
tsc启动时默认会查询项目根目录(项目根目录参考上面)以及祖先目录所有的node_modules/@types/* 目录中所有的软件包
typeRoots 指定查询的目录,当目录至少存在一个时才生效。否则会回退默认配置
types 指定@types中哪些目录会被加载。同上当目录至少存在一个时才会生效,否则回退。
rootDir 和 rootDirs
前者用于所有输入文件的最长路径,默认是自动计算的。 比如下面计算出路径是core/,当编译输出到outDir 会输出dist/a.js,会忽略前面core。如果想要保留core,把rootDir 修改成"./" 即可。
MyProj
├── tsconfig.json
├── core
│ ├── a.ts
│ ├── b.ts
│ ├── sub
│ │ ├── c.ts
├── types.d.tsrootDirs 用于虚拟目录,可以将两个在不同目录中文件,视为在一个目录。比如下a.ts 可以使用import b from "./b"
json
rootDirs: ["./core1", "./core2"]MyProj
├── tsconfig.json
├── core1
│ ├── a.ts
├── core2
│ ├── b.ts
├── types.d.tstsc如何加载软件包
tsc中import 语句
模块解析
如果tsconfig中moduleResolution: Node 时,按照node的模块查找规则。查找规则按照path+place 的方式
path是相对或者绝对路径时,直接按照路径解析。相对路径不包含 'xx/xxx' path是动态路径时,比如** import xx from 'xx' **。从当前文件开始查找同级目录是否存在node_modules/xx。
place规则如下
- xx.ts
- xx 中存在package.json 而且存在package.types所指的文件或者exports.types指定的文件
- @types/xx
- xx/index.ts
同时针对文件扩展名,按照.ts .tsx .d.ts 顺序解析。
另外还可以通过修改设置baseUrl和paths 映射来修改这种行为。默认情况下只要设置了baseUrl,paths会默认添加 { "": ["./"] } 配置
如果想追踪每个module的解析情况,可以使用traceResolution: true 打印解析日志 tsc编译时会从入口文件开始,将相关的依赖文件同时编译。如果配置了noResolve选项指定了某些模块不编译,编译会报错。
从变量引用和类型引用两个角度分析。
变量角度
ts
// test.ts
import { a } from "a" // 1. 寻找是否能根据baseUrl和paths匹配到模块 2.依次向上查询node_modules/a是否存在 3.如果是文件夹,先检查package.json描述,如果package.json 不存在,检查index.ts 是否存在。
import b from "a/b" // 1. 同上 2. 检查node_modules/a/b 是否存在。 3. 同上3
import c from './c' // 1. 检查是否配置了rootDirs。 2. ./c是否是文件夹,如果是参考1.3
import d from 'd.xx' // 1. 同上1类型角度
ts
// test.ts
import { a } from "a" // 1. 寻找是否能根据baseUrl和paths匹配到模块,a.ts存在,直接导出a.ts的命名空间,如果只有a.js存在,需要查找a.d.ts,如果a.d.ts未查找到,同时allowJS: false,在查询是否存在当前module的 declararion 声明,查找终止。
// 2. 向上查找node_modules/a.d.ts,如果是文件夹,先查找package.json相关定义,再查找node_modules/a/index.d.ts。再加载同级@types/a 文件夹,按照上述步骤处理。
import b from "a/b" // 1. 同上1 2.
import c from './c' // 1. 同上述文件夹处理方式 2. 检查是否有declaration 声明
import d from './d.xx' // 后缀当做文件名处理vscode中typescript
npm i -D typescript后。会安装typescript/core、tsc和tsserver。其中tsserver负责对vscode工作区文件的检查
declare
- 当一个d.ts 不存在export 或者import 会被视为全局文件。通过declare定义都是全局的,否则就是局部的。
- namespace 理解成同一个文件中的模块化。里面的定义需要通过export 导出。否则也是局部的。
vscode检查ts 结论
- 每次点开一个ts文件时,tsserver会使用这个文件最近tsconfig.json 文件,如果这个配置文件包含这个文件。则使用这个文件的规则。
- 如果这个tsconfig.json 不包含这个文件,比如被排除或者不在include范围内。就会使用项目根目录的tsconfig.json
- 如果项目根目录的tsconfig.json 也不包含这个文件。则会使用tsserver 默认的规则检查。
vscode检查js
如果开启allowjs会按照上面检查ts的流程检查,如果没有会按照先查询tsconfig.json ,再查询jsconfig.json 逻辑。
