使用 Vue JSX 时出现:JSX 元素隐式具有类型 “any“,因为不存在接口 “JSX.IntrinsicElements“。

这一段时间在为华为云的 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声明,这并不影响你将它放在任何特定位置,只要确保这个路径会被检查器识别即可。

这个错误提示表明在index.jsx文件的第9行发生了一个未捕获的错误,错误类型是ReferenceError,具体是React未定义。这通常是由于在使用React相关代码之前没有正确导入React库所致。 在Vue 3中,使用React库需要先安装并导入它。你可以通过以下步骤解决这个问题: 1. 确保已经安装了React库。可以使用npm或者yarn进行安装,命令如下: ``` npm install react ``` 或者 ``` yarn add react ``` 2. 在index.jsx文件的开头添加以下代码来导入React库: ```javascript import React from 'react'; ``` 如果你使用的是Vue 3的Composition API,还需要导入`reactivity`模块: ```javascript import { reactive } from 'vue'; import { createApp } from 'vue'; import { createRouter, createWebHistory } from 'vue-router'; import { createHead } from '@vueuse/head'; import { useMeta } from 'vue-meta'; import { useStore } from 'vuex'; import { useRoute } from 'vue-router'; import { useRouter } from 'vue-router'; import { useHead } from '@vueuse/head'; import { useMetaTags } from 'vue-meta-tags'; import { ref, computed, watch, onMounted, onUnmounted } from 'vue'; import { reactive, toRefs } from 'vue'; import { provide, inject } from 'vue'; import { nextTick } from 'vue'; import { defineComponent } from 'vue'; import { h } from 'vue'; import { withModifiers } from 'vue'; import { onBeforeMount } from 'vue'; import { onMounted } from 'vue'; import { onBeforeUnmount } from 'vue'; import { onUnmounted } from 'vue'; import { onBeforeUpdate } from 'vue'; import { onUpdated } from 'vue'; import { onErrorCaptured } from 'vue'; import { onRenderTracked } from 'vue'; import { onRenderTriggered } from 'vue'; import { watchEffect } from 'vue'; import { watchPostEffect } from 'vue'; import { watchEffectOnce } from 'vue'; import { watchPostEffectOnce } from 'vue'; import { watchEffectAsync } from 'vue'; import { watchPostEffectAsync } from 'vue'; ``` 3. 确保你的代码中正确使用了React相关的组件和语法。 希望这些步骤能够帮助你解决问题!如果还有其他问题,请随提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值