React+TypeScript报错:Property 'children' does not exist on type 'IntrinsicAttributes'
解决React + TypeScript中“Property 'children' does not exist on type 'IntrinsicAttributes'”错误
错误提示Property 'children' does not exist on type 'IntrinsicAttributes'通常出现在React组件渲染时,JSX元素预期的属性与实际传入的props不匹配,多和动态组件的类型推断错误有关。以下是触发该错误的代码:
import React from "react"; import PropTypes, { Requireable } from "prop-types"; interface TypographyProps { variant: "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "p1" | "p2"; children: React.ReactNode; className?: string; font?: string; } const Typography: React.FC<TypographyProps> = ({ variant, children, className, font, ...restProps }) => { const variantMapping = { h1: { variant: "h1", classes: "2xl:text-[64px] lg:text-5xl md:text-4xl sm:text-3xl text-2xl leading-normal font-lato_bold", }, h2: { variant: "h2", classes: "2xl:text-5xl lg:text-3xl md:text-2xl text-xl font-lato font-bold", }, h3: { variant: "h3", classes: "2xl:text-4xl lg:text-2xl md:text-xl text-lg font-lato font-bold", }, h4: { variant: "h4", classes: "2xl:text-[32px] lg:text-xl sm:text-lg text-lg font-lato !font-bold ", }, h5: { variant: "h5", classes: "2xl:text-2xl md:text-lg sm:text-base text-sm font-lato font-medium ", }, h6: { variant: "h6", classes: "2xl:text-xl lg:text-base text-sm font-lato font-medium", }, p: { variant: "p", classes: "2xl:text-lg xl:text-base md:text-sm text-xs font-lato font-medium", }, p1: { variant: "p", classes: "2xl:text-base md:text-sm text-xs font-lato font-regular ", }, p2: { variant: "p", classes: "2xl:text-sm text-xs font-lato font-regular ", }, }; const classes = variantMapping[variant]?.classes || ""; const Component = variantMapping[variant]?.variant || "p"; return ( <Component className={`${classes} ${className}`} {...restProps}> {children} </Component> ); }; Typography.propTypes = { variant: PropTypes.oneOf([ "h1", "h2", "h3", "h4", "h5", "h6", "p", "p1", "p2", ]).isRequired as Requireable<TypographyProps["variant"]>, children: PropTypes.node.isRequired, className: PropTypes.string, }; Typography.defaultProps = { className: "", variant: "h3" as TypographyProps["variant"], }; export default Typography;
错误原因
TypeScript将Component变量推断为普通字符串类型(如"h1"、"p"),而非React可识别的元素类型。当你尝试给这个字符串类型的"组件"传入className、children等props时,TypeScript无法识别这些属性,因此抛出类型不匹配的错误。
解决方案
方案1:为variantMapping定义明确的类型
通过定义类型约束,让TypeScript明确知道variant字段是有效的HTML元素类型:
// 定义允许的HTML标签类型 type ValidHTMLTag = "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p"; interface VariantMappingItem { variant: ValidHTMLTag; classes: string; } // 给variantMapping加上类型约束 const variantMapping: Record<TypographyProps["variant"], VariantMappingItem> = { // 原映射内容保持不变 h1: { variant: "h1", classes: "2xl:text-[64px] lg:text-5xl md:text-4xl sm:text-3xl text-2xl leading-normal font-lato_bold", }, // ...其他映射项 };
方案2:直接断言Component为React.ElementType
快速修复的方式是将Component断言为React元素类型,让TypeScript认可它能接收标准React props:
const Component = variantMapping[variant]?.variant as React.ElementType || "p";
额外优化:处理className空值问题
避免className为空时生成多余空格,可修改为:
const combinedClassName = [classes, className].filter(Boolean).join(" "); return ( <Component className={combinedClassName} {...restProps}> {children} </Component> );
修改后的完整代码
import React from "react"; import PropTypes, { Requireable } from "prop-types"; interface TypographyProps { variant: "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "p1" | "p2"; children: React.ReactNode; className?: string; font?: string; } type ValidHTMLTag = "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p"; interface VariantMappingItem { variant: ValidHTMLTag; classes: string; } const Typography: React.FC<TypographyProps> = ({ variant, children, className, font, ...restProps }) => { const variantMapping: Record<TypographyProps["variant"], VariantMappingItem> = { h1: { variant: "h1", classes: "2xl:text-[64px] lg:text-5xl md:text-4xl sm:text-3xl text-2xl leading-normal font-lato_bold", }, h2: { variant: "h2", classes: "2xl:text-5xl lg:text-3xl md:text-2xl text-xl font-lato font-bold", }, h3: { variant: "h3", classes: "2xl:text-4xl lg:text-2xl md:text-xl text-lg font-lato font-bold", }, h4: { variant: "h4", classes: "2xl:text-[32px] lg:text-xl sm:text-lg text-lg font-lato !font-bold ", }, h5: { variant: "h5", classes: "2xl:text-2xl md:text-lg sm:text-base text-sm font-lato font-medium ", }, h6: { variant: "h6", classes: "2xl:text-xl lg:text-base text-sm font-lato font-medium", }, p: { variant: "p", classes: "2xl:text-lg xl:text-base md:text-sm text-xs font-lato font-medium", }, p1: { variant: "p", classes: "2xl:text-base md:text-sm text-xs font-lato font-regular ", }, p2: { variant: "p", classes: "2xl:text-sm text-xs font-lato font-regular ", }, }; const { classes, variant: tagName } = variantMapping[variant]; const Component = tagName; const combinedClassName = [classes, className].filter(Boolean).join(" "); return ( <Component className={combinedClassName} {...restProps}> {children} </Component> ); }; Typography.propTypes = { variant: PropTypes.oneOf([ "h1", "h2", "h3", "h4", "h5", "h6", "p", "p1", "p2", ]).isRequired as Requireable<TypographyProps["variant"]>, children: PropTypes.node.isRequired, className: PropTypes.string, }; Typography.defaultProps = { className: "", variant: "h3" as TypographyProps["variant"], }; export default Typography;
内容的提问来源于stack exchange,提问作者Muhammad Saif ur Rehman
相关产品推荐
相关产品推荐

