🐱 个人主页:不叫猫先生,公众号:前端舵手
🙋♂️ 作者简介:2022年度博客之星前端领域TOP 2,前端领域优质作者、阿里云专家博主,专注于前端各领域技术,共同学习共同进步,一起加油呀!
💫优质专栏:vue3+vite+typeScript从入门到实践
📢 资料领取:前端进阶资料可以找我免费领取
🔥 摸鱼学习交流:我们的宗旨是在「工作中摸鱼,摸鱼中进步」,期待大佬一起来摸鱼(文末有我wx或者私信)。
目录
- 背景
- 问题描述
- 分析
- 解决
背景
当我们新建vue3项目,package.json文件会自动给我添加一些配置选项,这写选项基本没有问题,但是在实际操作过程中,当项目越来越复杂就会出现问题。本文列举一个目前我遇到的一个问题:打包后报了一堆TS类型错误,怎么消除这些错误?
项目环境:Vue3 + Vite + TS
问题描述
当项目进行打包时候,突然发现终端有几十项报错
npm run build
复制
详细报错信息如下:
src/view/testDemo/index.vue:6:9 - error TS2339: Property 'proxy' does not exist on type 'ComponentInternalInstance | null'. 6 const { proxy } = getCurrentInstance(); ~~~~~ src/view/echarts/index.vue:7:9 - error TS2339: Property 'proxy' does not exist on type 'ComponentInternalInstance | null'. 7 const { proxy } = getCurrentInstance(); ~~~~~ src/view/webRTC/index.vue:5:23 - error TS2322: Type 'string | number' is not assignable to type 'string | undefined'. Type 'number' is not assignable to type 'string'. 5 <img :src=" item" alt="" /> ~~~ node_modules/@vue/runtime-dom/dist/runtime-dom.d.ts:616:3 616 src?: string ~~~ The expected type comes from property 'src' which is declared here on type 'ElementAttrs<ImgHTMLAttributes>' src/view/webRTC/index.vue:13:55 - error TS2322: Type '(deviceId: string) => Promise<void>' is not assignable to type '(evt: MouseEvent) => any'. Types of parameters 'deviceId' and 'evt' are incompatible. Type 'MouseEvent' is not assignable to type 'string'. 13 <el-button type="primary" size="default" @click="handleDeviceChange"> ~~~~~ src/layout/index.vue:14:22 - error TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & Partial<{ readonly disabled: boolean; readonly showTimeout: number; readonly hideTimeout: number; readonly popperAppendToBody: EpPropMergeType<BooleanConstructor, unknown, unknown>; readonly popperOffset: number; }> & Omit<...>'. Property 'index' is missing in type '{}' but required in type 'Omit<Readonly<ExtractPropTypes<{ readonly index: { readonly type: PropType<string>; readonly required: true; readonly validator: ((val: unknown) => boolean) | undefined; __epPropKey: true; }; readonly showTimeout: EpPropFinalized<...>; ... 8 more ...; readonly collapseOpenIcon: { ...; }; }>> & VNodeProps & AllowedCo...'. 14 <el-sub-menu> ~~~~~~~~~~~ node_modules/element-plus/es/components/menu/index.d.ts:363:14 363 readonly index: { ~~~~~ 'index' is declared here. src/view/testDemo/index.vue:27:32 - error TS2345: Argument of type 'HTMLElement | null' is not assignable to parameter of type 'HTMLElement'. Type 'null' is not assignable to type 'HTMLElement'. 27 var myChart = echarts.init(document.getElementById("trendLIne-content")); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ src/view/testDemo/index_.vue:41:40 - error TS2552: Cannot find name 'myData'. Did you mean 'data'? 41 value: myData[dataIndex], ~~~~~~ src/view/testDemo/index_.vue:7:5 7 let data = reactive([ ~~~~ 'data' is declared here. src/view/echarts/index.vue:40:32 - error TS2345: Argument of type 'HTMLElement | null' is not assignable to parameter of type 'HTMLElement'. Type 'null' is not assignable to type 'HTMLElement'. 40 var myChart = echarts.init(document.getElementById("trendLIne-content")); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ src/view/testDemo/index.vue:42:40 - error TS2552: Cannot find name 'myData'. Did you mean 'data'? 42 value: myData[dataIndex], ~~~~~~ src/view/testDemo/index.vue:7:5 7 let data = reactive([ ~~~~ 'data' is declared here. src/layout/index.vue:65:20 - error TS2339: Property '$fil' does not exist on type 'ComponentPublicInstance<{}, {}, {}, {}, {}, {}, {}, {}, false, ComponentOptionsBase<any, any, any, any, any, any, any, any, any, {}, {}, string>, {}>'. 65 console.log(proxy?.$fil, "proxy"); ~~~~ src/view/webRTC/index.vue:136:5 - error TS2322: Type '{ facingMode: string; }' is not assignable to type 'boolean'. 136 constraints.video = { ~~~~~~~~~~~~~~~~~ src/view/webRTC/index.vue:146:13 - error TS2304: Cannot find name 'ElMessage'. 146 ElMessage.success("切换成功"); ~~~~~~~~~ src/view/webRTC/index.vue:150:13 - error TS2304: Cannot find name 'ElMessage'. 150 ElMessage.error("你的设备不支持切换前后摄像头"); ~~~~~~~~~ src/view/webRTC/index.vue:156:28 - error TS2304: Cannot find name 'multiavatar'. 156 const blob = new Blob([multiavatar(val + new Date().getTime())], { ~~~~~~~~~~~ src/view/testDemo/index.vue:168:9 - error TS1117: An object literal cannot have multiple properties with the same name. 168 grid: { ~~~~ src/directives/canvasMakeWaterMark.ts:30:3 - error TS18047: 'ctx' is possibly 'null'. 30 ctx.rotate((rotate * Math.PI) / 180); ~~~ src/directives/canvasMakeWaterMark.ts:31:3 - error TS18047: 'ctx' is possibly 'null'. 31 ctx.font = "16px normal"; ~~~ src/directives/canvasMakeWaterMark.ts:32:3 - error TS18047: 'ctx' is possibly 'null'. 32 ctx.fillStyle = "rgba(180, 180, 180, 0.3)"; ~~~ src/directives/canvasMakeWaterMark.ts:33:3 - error TS18047: 'ctx' is possibly 'null'. 33 ctx.textAlign = "left"; ~~~ src/directives/canvasMakeWaterMark.ts:34:3 - error TS18047: 'ctx' is possibly 'null'. 34 ctx.textBaseline = "middle"; ~~~ src/directives/canvasMakeWaterMark.ts:35:3 - error TS18047: 'ctx' is possibly 'null'. 35 ctx.fillText('请勿外传', canvas.width / 3, canvas.height / 2); ~~~ src/directives/canvasMakeWaterMark.ts:59:26 - error TS2554: Expected 0 arguments, but got 1. 59 const url = getDataUrl(binding); ~~~~~~~ src/directives/canvasMakeWaterMark.ts:68:3 - error TS18047: 'parentElement' is possibly 'null'. 68 parentElement.setAttribute("style", "position: relative;"); ~~~~~~~~~~~~~ src/directives/canvasMakeWaterMark.ts:71:3 - error TS18047: 'parentElement' is possibly 'null'. 71 parentElement.appendChild(waterMark); ~~~~~~~~~~~~~ src/directives/canvasMakeWaterMark.ts:81:23 - error TS18047: 'el.parentElement' is possibly 'null'. 81 const waterMarkEl = el.parentElement.querySelector(".water-mark"); ~~~~~~~~~~~~~~~~ src/directives/canvasMakeWaterMark.ts:87:25 - error TS18047: 'waterMarkEl' is possibly 'null'. 87 const currStyle = waterMarkEl.getAttribute("style"); ~~~~~~~~~~~ src/directives/canvasMakeWaterMark.ts:116:20 - error TS2345: Argument of type 'HTMLElement | null' is not assignable to parameter of type 'Node'. Type 'null' is not assignable to type 'Node'. 116 observer.observe(el.parentElement, { ~~~~~~~~~~~~~~~~
复制
截图图片如下:
分析
打包执行的是npm run build
命令,那么具体执行了什么呢?我们查看package.json
中配置项。
"scripts": { "dev": "vite", "build": "vue-tsc --noEmit && vite build", "preview": "vite preview" },
复制
可以发现在build
时,执行了vue-tsc --noEmit && vite build
,其中
-
vue-tsc
:Vue 官方提供的命令,用于执行 TS 的类型检查。它在执行时会根据项目中的 tsconfig.json 文件配置进行类型检查 -
--noEmit
:TS 编译器的选项,使用 --noEmit 选项后,编译器仅执行类型检查,而不会生成任何实际的编译输出
所以可以看出了,在打包的时候编译器执行了TS类型检查,所以才报了一堆错,类型错误最终不会影响项目的正常运行
解决
根据上面分析,package.json
中的"scripts"
修改如下:
"scripts": { "dev": "vite", "build": "vite build", "preview": "vite preview" },
复制
另外项目通常在编译时候,也会对我们引入的一些依赖包进行类型校验,我们并不需要这个操作,所以可以在tsconfig.json
中设置如下:
"compilerOptions": { "skipLibCheck": true },
复制
设置后编译器不会检查库文件中的类型定义是否正确,也不会对库文件的使用进行类型检查。
再次打包就非常顺利~