JSX转TSX时craft.js中Element组件is属性类型不兼容问题
is属性类型错误原因分析 在使用refine.dev和craft.js开发应用、将JSX转为TSX的过程中,在<Element is={Container} />处出现类型错误,以下是相关代码及错误详情:
Builder组件代码
import { Button, Image, Text } from "@shared/components/atoms/components"; import { ColumnRules, Container, FourCol, OneCol, ThreeCol, TwoCol } from "@shared/components/layout/components"; interface BuilderProps { onBuilderStatePersist: (value: string) => void; initialBuilderState: { buildState: string }; } export const Builder = ({ onBuilderStatePersist, initialBuilderState }: BuilderProps) => { [...] return ( <div style={{ margin: "0 auto", width: "100%", position: "relative" }}> <Editor resolver={{ // 自定义组件配置 }} > <Grid item xs> <Frame data={builderStateRef.current}> <Element is={Container} padding={5} background="#eee" canvas /> </Frame> </Grid> </Grid> </Editor> </div> ); };
Container组件代码
import { HTMLAttributes, ReactNode } from "react"; import { useNode } from "@craftjs/core"; import { Paper } from "@mui/material"; interface ContainerProps extends HTMLAttributes<HTMLDivElement> { id: string; background?: string; backgroundColor?: string; borderRadius?: string; padding?: number; children?: ReactNode; } export const Container = ({ background, padding = 0, children, ...props }: ContainerProps) => { const { connectors: { connect, drag }, } = useNode(); return ( <Paper {...props} ref={(ref) => ref && connect(drag(ref!))} style={{ margin: "5px 0", background, padding: `${padding}px` }} > {children} </Paper> ); };
错误提示
Type '({ background, padding, children, ...props }: ContainerProps) => JSX.Element' is not assignable to type '(({ background, padding, children, ...props }: ContainerProps) => Element) & string'.
Type '({ background, padding, children, ...props }: ContainerProps) => JSX.Element' is not assignable to type 'string'.ts(2322)
Element.d.ts(15, 5): The expected type comes from property 'is' which is declared here on type 'IntrinsicAttributes & { id?: string | undefined; is?: (({ background, padding, children, ...props }: ContainerProps) => Element) | undefined; custom?: Record<string, any> | undefined; children?: ReactNode; canvas?: boolean | undefined; } & ContainerProps'
(property) is?: ((({ background, padding, children, ...props }: ContainerProps) => JSX.Element) & string) | undefined
错误原因
核心问题是类型交叉导致的属性冲突:
- ContainerProps继承了
HTMLAttributes<HTMLDivElement>,而HTML原生的<div>元素有一个is属性(用于自定义内置元素,类型为string)。 - Craft.js的
<Element>组件本身定义了is属性,用于指定要渲染的自定义组件,类型为组件函数。 - 当
<Element>的Props与ContainerProps交叉合并时,is属性的类型变成了组件函数类型 & string——这是一个不可能同时满足的交集类型。你传入的Container是组件函数,无法匹配string类型,因此触发类型错误。
内容的提问来源于stack exchange,提问作者Johan

