TS报错ParentNode无getBoundingClientRect属性的解决方法
报错原因
TypeScript 对 DOM 节点parentNode属性的默认类型定义为ParentNode,这是覆盖Element、Document、DocumentFragment的联合类型。其中Document、DocumentFragment不存在getBoundingClientRect方法,只有Element类型的页面元素支持该方法,因此类型检查会拦截调用、抛出错误。
解决方案
可根据实际场景选择以下任意一种方案:
方案1:使用
parentElement替代parentNode(最推荐)
DOM 元素原生提供parentElement属性,返回值类型本身就是HTMLElement | null,只有当父节点是页面元素时才会返回对应值,否则返回null,完全匹配调用getBoundingClientRect的场景,不需要额外做类型处理:const menuWrapper = useRef<HTMLElement>(null); const parentElement = menuWrapper?.current?.parentElement; // 加空值兜底避免解构报错 const { top, left, height, width } = parentElement?.getBoundingClientRect() ?? { top: 0, left: 0, height: 0, width: 0 }; return ( <div ref={menuWrapper}> ... </div> )方案2:运行时类型收窄(最严谨)
如果需要兼容特殊场景、不想做硬类型断言,可以通过instanceof判断父节点类型,TypeScript 会自动完成类型收窄,同时规避运行时错误:const menuWrapper = useRef<HTMLElement>(null); const parentNode = menuWrapper?.current?.parentNode; const defaultRect = { top: 0, left: 0, height: 0, width: 0 }; let rect = defaultRect; if (parentNode instanceof HTMLElement) { rect = parentNode.getBoundingClientRect(); } const { top, left, height, width } = rect; return ( <div ref={menuWrapper}> ... </div> )方案3:类型断言(最直接)
如果可以100%确定当前节点的父节点一定是HTMLElement类型,可以直接通过类型断言指定值的类型,注意要补充空值兜底:const menuWrapper = useRef<HTMLElement>(null); const parentNode = menuWrapper?.current?.parentNode as HTMLElement | null; const { top, left, height, width } = parentNode?.getBoundingClientRect() ?? { top: 0, left: 0, height: 0, width: 0 }; return ( <div ref={menuWrapper}> ... </div> )
注意:不要在无任何判断的情况下直接使用非空断言
!跳过类型检查,一旦父节点不存在或者类型不符合预期,会直接抛出运行时错误。
内容的提问来源于stack exchange,提问作者Enis
相关产品推荐
相关产品推荐

