在引用公司的某个埋点包以后,发现vscode一直找不对它正确的类型定义,同样tsc编译的时候,也提示该包的定义文件上没有xx事件。于是开始排查
背景
首先项目node_modules结构如下:
本地代码 c.tsx
import log from 'B'
log.on()
其中B(5.0)的index.d.ts定义如下所示
interface Sdk {
on(type: string, hook: SdkHookListener): void;
}
B(4.0)的index.d.ts定义如下所示,其中4.0里面是没有on函数的定义的
declare module 'log' {
xxxx
}
原因
去查找了typescript的相关文档,查看module resolution这一章。首先ts解析是有两个类型的: classic和node,由于配置的是node,所以看看node的策略。ts解析no-relative的包的策略是基于node的策略进行了相关拓展。
先看一下node的策略,详细可以看看这个链接,这里看一下重点
然后ts在node寻找策略的基础上,覆盖了extension,从index.js变为ts、tsx、d.ts。所以,当ts解析一个no-relative的包时,它的路径如下所示
但是即使按照上面的规则,在当前例子下,解析的应该也是B(5.0)的包,而不是B(4.0)的包,why? 4.0的版本有如此高的优先级?
然后,又翻烂了typescript的module这一章的文档,发现了关键词 Ambient Modules
这个定义和B(4.0)不是很像吗? 可能稍微有点区别就是使用的时候,ambient modules需要增加reference关键词。ok,再往下翻
也就是说,如果declare module的名称和包名一样的话,引用的时候就不用增加reference关键词。然后呢? 它的优先级是怎么回事?typescript官方文档翻烂了,也没有写。
就在快绝望时候,发现了这样一篇issue:
根据上面的算法,官方已经告诉你了Ambient external Modules的优先级是最高的(完美符合B(4.0)包的定义),接下来才会按照module resolution的策略开始寻找。
解决
解决方案挺简单,在tsconfig.json增加一行这样配置
"compilerOptions": {
"baseUrl": "src",
"paths": {
"log": [
"../node_modules/log"
]
}
},