TypeScript环境下React递归克隆children时props不存在报错如何解决?
问题解决方案
报错原因
React.Children.map 回调的入参 child 类型为 React.ReactNode,它包含字符串、数字、空值、元素数组、React元素等多种类型,你仅用 isObject 判断无法排除没有props属性的空对象、节点数组、ReactPortal等类型,因此TS会抛出属性不存在的报错。直接强转child为React.ReactChild会破坏类型安全,且无法匹配children入参的React.ReactNode类型约束,因此会出现新的类型错误。
解决方法
使用React官方提供的React.isValidElement类型守卫判断节点类型,它会自动完成类型缩小,通过判断后的child会被TS自动识别为React.ReactElement类型,访问props属性就不会报错。
修改后的完整代码
import React, { isValidElement, ReactNode } from 'react'; // 请根据你的实际业务调整handleChildChange的类型定义 type HandleChildChange = (...args: any[]) => void; export const recursiveCloneChildren = ( children: ReactNode, handleChildChange: HandleChildChange, disableContent: boolean, ): ReactNode => { return React.Children.map(children, (child) => { // 替换原来的isObject判断,用官方的类型守卫 if (!isValidElement(child)) { return child; } let childProps = { ...child.props, disabled: child.props.disabled || disableContent, }; const requiredOrValidatableChildProps = { ...childProps, checkValidationState: handleChildChange, }; if (child.props.required || child.props.validatable) { childProps = { ...requiredOrValidatableChildProps, }; } if (child.props.children) { childProps.children = recursiveCloneChildren(child.props.children, handleChildChange, disableContent); } return React.cloneElement(child, childProps); }); };
补充说明
如果需要更严格的类型约束,你可以给ReactElement指定泛型,限制props的类型,进一步提升类型安全性。
内容的提问来源于stack exchange,提问作者Norayr Ghukasyan
相关产品推荐
相关产品推荐

