TS2339报错:useRef推导current为never无getBoundingClientRect,求非@ts-ignore解法
报错根因
- 你调用
useRef()的时候没传泛型参数,TS会直接匹配React类型定义里的无参重载,把返回值推导成MutableRefObject<undefined>——说白了就是这个ref对象从类型定义上就不可能是undefined,你写的第一层ref !== undefined判断对TS来说是永远成立的,半毛钱类型收窄效果都没有 ref.hasOwnProperty('current')根本不是TS认可的类型守卫,触发不了任何类型收窄,TS还是会把ref.current当成原本的undefined类型- 等走到第三层
ref.current !== undefined && ref.current !== null判断的时候,原本的undefined类型被你完全排除了,剩下的分支类型自然就被TS推成了never,never类型上不存在任何方法,自然会报找不到getBoundingClientRect的错 - 整个判断链路的问题本质是:你没从泛型定义层面把ref的实际类型对齐,反而靠写运行时判断去“凑”类型,TS是不认这类非标准判断逻辑的;你最后加的可选链也救不了报错——可选链只是规避运行时空值问题,改变不了TS已经把
ref.current推成never的类型判定,never类型上哪怕加可选链,访问方法依然会报类型错误
合规解决方案(完全不用@ts-ignore)
- 第一步给
useRef补上明确的泛型定义,从根源对齐DOM元素的实际类型,别靠运行时判断硬补:
这时候// 根据实际绑定的DOM元素调整泛型,绑div就用HTMLDivElement,绑canvas就用HTMLCanvasElement const ref = useRef<HTMLDivElement>(null)ref.current的类型会被自动推导为HTMLDivElement | null,完整包含getBoundingClientRect的方法定义 - 第二步删掉那些没有类型收窄效果的冗余判断,直接用TS能识别的空值判断做收窄就行:
直接判断if (ref.current) { console.log(ref.current.getBoundingClientRect()) }ref.current真假值的逻辑是TS原生支持的收窄规则,会自动把null类型排除,剩下的就是纯HTMLDivElement类型,根本不会触发类型报错 - 如果是老项目里没法直接给
useRef改泛型、传初始值的场景,可以用TS内置的类型守卫替换掉没效果的hasOwnProperty判断:if (ref.current instanceof Element) { console.log(ref.current.getBoundingClientRect()) }instanceof是TS原生支持的类型守卫,能直接把ref.current的类型收窄为Element,从根源避免出现never类型的问题
内容的提问来源于stack exchange,提问作者Atrag
相关产品推荐
相关产品推荐

