React中使用child.type时如何解决TypeScript报错问题
修复React TypeScript组件中child.type的类型错误
问题场景
在以下React TypeScript组件中,TypeScript在child.type处报错:
参数类型'string | JSXElementConstructor'无法赋值给类型'(({ src, alt }: CardImageProps) => Element) | (({ children }: CardBodyProps) => Element)'。类型'string'无法赋值给该联合类型。
原组件代码:
const Card = ({ children }:CardProps) => { const allowed = [CardImage, CardBody]; return ( <div {React.Children.map(children, (child) => { if (!allowed.includes(child.type)) return; return child; })} </div> ); }; Card.Image = CardImage; Card.Body = CardBody; export default Card;
修复方案
1. 明确允许的组件类型
先给allowed数组指定精确的类型,让TypeScript明确数组元素都是自定义组件:
// 定义允许的组件类型 type AllowedCardComponent = typeof CardImage | typeof CardBody; // 给allowed数组绑定类型 const allowed: AllowedCardComponent[] = [CardImage, CardBody];
2. 过滤原生标签+类型断言
child.type可能是字符串(对应原生HTML标签,比如div),需要先排除这种情况,再用类型断言告诉TypeScript当前child.type属于允许的组件类型:
React.Children.map(children, (child) => { // 跳过原生HTML标签 if (typeof child.type === 'string') return null; // 断言类型后检查是否在允许列表中 if (!allowed.includes(child.type as AllowedCardComponent)) return null; return child; })
3. 完整修复后的代码
import React from 'react'; // 假设基础类型已定义 interface CardProps { children: React.ReactNode; } interface CardImageProps { src: string; alt: string; } const CardImage = ({ src, alt }: CardImageProps) => <img src={src} alt={alt} />; interface CardBodyProps { children: React.ReactNode; } const CardBody = ({ children }: CardBodyProps) => <div>{children}</div>; const Card = ({ children }: CardProps) => { type AllowedCardComponent = typeof CardImage | typeof CardBody; const allowed: AllowedCardComponent[] = [CardImage, CardBody]; return ( <div> {React.Children.map(children, (child) => { if (typeof child.type === 'string') return null; if (!allowed.includes(child.type as AllowedCardComponent)) return null; return child; })} </div> ); }; Card.Image = CardImage; Card.Body = CardBody; export default Card;
可选:用类型守卫提升严谨性
如果想要更规范的类型检查,可以自定义类型守卫函数替代类型断言:
function isAllowedCardComponent( type: string | JSXElementConstructor<any> ): type is AllowedCardComponent { return allowed.includes(type as AllowedCardComponent); }
之后在map中这样判断:
React.Children.map(children, (child) => { if (!isAllowedCardComponent(child.type)) return null; return child; })
内容的提问来源于stack exchange,提问作者meez
相关产品推荐
相关产品推荐

