使用volar验证TS useClickOutside参数类型错误

来源:4-11 useClickOutside 第一个自定义函数

辰辰ollie

2021-08-24

//Dropdown.vue
const dropdownRef = ref<null | HTMLElement>(null)
const isClickOutside = useClickOutside(dropdownRef)
//...其他代码
//useClickOutside.ts

const useClickOutside = (elementRef: Ref<null | HTMLElement>): Ref<boolean> => {
  const isClickOutside = ref(false)
  const handler = (e: MouseEvent) => {
    if (elementRef.value) {
      if (elementRef.value.contains(e.target as HTMLElement)) {
        isClickOutside.value = false
      } else {
        isClickOutside.value = true
      }
    }
  }
  onMounted(() => {
    document.addEventListener('click', handler)
  })
  onUnmounted(() => {
    document.removeEventListener('click', handler)
  })
  return isClickOutside
}

老师你好:
项目中使用了volar来做ts效验,原来使用vetur是没问题的,换成volar后类型出现以下错误,如图
图片描述

尤雨溪已经说了未来volar会替代vetur成为新的工具,所以麻烦老师可以帮忙看看怎么解决。
项目地址:https://github.com/ollieSk8/zhihu-project

写回答

2回答

张轩

2021-08-25

同学你好 看了一下 这里我认为 volar 的实现有可能有点问题 它会将 HTMLElement 类型直接展开,造成类型的不匹配,暂时解决这个问题,可以使用 any 大法,或者去掉泛型让它推论成 null 类型,都可以。

const dropdownRef = ref(null)
const dropdownRef = ref<any>(null)

 

0
2
辰辰ollie
老师我提了个issues,作者也回复了,他说这只是一个vue类型问题,后边没太明白啥意思,有时间可以帮忙看下么 地址https://github.com/johnsoncodehk/volar/issues/416
2021-08-25
共2条回复

张轩

2021-08-25

同学 给你提issue 精神赞一个,非常好。我要好好宣扬一下,他回答就是说这个错误和 volar 没关系。

我今天又仔细看了一下,应该是 vue 的定义文件升级有关系。

export declare function ref<T>(value: T): Ref<UnwrapRef<T>>;

当调用 ref 有值的时候会将 T 类型自动展开,这样就会造成不匹配,假如你不想用上个回答的 any 大法。可以这样改,将 useClickOutside 的接受的参数也展开,让他两匹配即可。

// useClickOutside 把  UnwrapRef 引进来
import { ref, onMounted, onUnmounted, Ref, UnwrapRef } from 'vue'
参数定义为 UnwrapRef 类型
const useClickOutside = (elementRef: Ref<null | UnwrapRef<HTMLElement>>)

这样就没有错误了,当然这样只是为了类型通过,也比较繁琐,建议还是直接 any 或者 不加泛型,要让ts 为我们服务,不要追求极致。

0
1
辰辰ollie
好的 ,感觉老师的耐心
2021-08-25
共1条回复

Vue3 + TS 仿知乎专栏企业级项目

带你完成前后端分离复杂项目,率先掌握 vue3 造轮子技能

3074 学习 · 2253 问题

查看课程