这一段时间在为华为云的 Vue DevUI 组件库(一个前端组件库)做开源贡献。每次在 VSCode 中打开整个项目的时候都发现里面所有.tsx
结尾的文件都是大面积爆红,我查看了一下报错内容:JSX 元素隐式具有类型 "any",因为不存在接口 "JSX.IntrinsicElements"。
作为一个晚期的强迫症患者,看到这个情况,这能忍?虽然其实这并不影响使用,但是每每想到我的代码中到处都是爆红,实在是令人头皮发麻。
于是我立刻把报错内容复制粘贴,在必应上四处搜寻,不少博客都建议我安装@types/react
和@types/react-dom
,但是我们的组件库是 Vue JSX,而和 Vue 相关的博客里,得到的结论都是清一色的“不使用严格的类型检查”。
要么是:
{
"compilerOptions": {
"strict": false
}
}
这个是禁用严格检查,意思是让检查器对你宽容一些,一些小问题就别 cue 我了。
要么是:
{
"compilerOptions": {
"noImplicitAny": false,
}
}
这个倒是更加一针见血,是禁用在出现表达式和声明上有隐含的any
的时候抛出异常,让它对类似的异常忽略。它直接针对我们遇到的这个问题,让这类问题被忽略掉。好吧,你这边给我报这个错误,报错报的很好,以后别报了。
实际上本质上上面这两个其实解决方案是一个,都是降级代码检查的严格程度。要硬说这两种都的确都是有效解决方案,但是实在是略有些简单粗暴,没有任何优雅性可言。更何况我提交一个把strict
改成false
的 PR 的话,感觉还是略有些生草。
后来我又想到可以配置@vue/babel-preset-jsx
,但是这个也没有解决JSX
语法报错的问题(我怀疑可能是依赖不匹配的问题),最后我还是想到了一个稍微优雅一些的方案:
// src/shims-vue.d.ts
import { VNode } from 'vue';
declare type VueNode = VNode;
declare global {
namespace JSX {
interface IntrinsicElements {
[elem: string]: unknown;
}
}
}
这里使用unknown
是因为 TypeScript 非常排斥开发者使用一个宽泛的类型声明,接受任何类型的相关值,所以我没有使用any
而是使用了官方推荐的unknown
作为替代。
这个文件可以放在任何一个src
路径中,由于 DevUI 是一个组件库,所以我将它放在了外层的根目录中。实际上,这里使用了global
声明,这并不影响你将它放在任何特定位置,只要确保这个路径会被检查器识别即可。