首页 > 解决方案 > Typescript 和 React:类型“元素”不可分配给类型“FunctionComponent<{}>”

问题描述

我正在将一个反应项目转换为打字稿,但我遇到了问题。场景是这样的:我有一系列Chapter组件。每个Chapter都与它自己独特的数据和独特的Map组件相关联。每个Chapter渲染一个,并作为一个道具ChapterTemplate传递:Map

// Chapter.tsx

import model from './modal';
import Map from './Map';

type ChapterProps = {
    data: ModelSchema;
    map: ReactElement;
};

const Chapter: FunctionComponent<ChapterProps> = () => {
    return <ChapterTemplate data={model} map={<Map />} />;
};

这给了我以下 ts 错误map={<Map />}

Type 'Element' is not assignable to type 'FunctionComponent<{}>'. Type 'Element' provides no match for the signature '(props: { children?: ReactNode; }, context?: any): ReactElement<any, any>'.

我不确定如何根据我的使用方式键入此道具。

在某些情况下,<Map />组件应如下所示:

type MapProps = {
    metadata?: {
        name: string;
        theme: string;
    };
    mapState?: {
        center: number[];
        zoom: number;
        basemap: any;
        layers: any[];
    };
};

const Map = ({
    metadata,
    mapState: { basemap, layers, zoom, center },
}: MapProps) => {
  
  // ... custom logic here for each chapter ...

}

最终,它是ChapterTemplate组织数据、管理状态并将某些数据片段传递给Mapas 道具的组件,使用React.cloneElement

const Chapter = ({
  map,
  data: { pages, metadata },
}: ChapterProps) => {
  const [currentPage, setCurrentPage] = useState(0);
  const Map = map;

  return (
    <Wrapper>
      // Some other stuff in here
      <MapContainer>
        {cloneElement(map as null, {
          mapState: pages[currentPage].mapState,
          metadata,
        })}
      </MapContainer>
    </Wrapper>
  );
};

我阅读了问题如何在为孩子提供属性时为 React.cloneElement 分配正确的类型?,这就是我想到将ReactElement其用作map道具类型的地方。我尝试map as ReactElement<any>在我的cloneElement通话中使用,但它仍然给我错误,所以我放弃并暂时加入as null。但我仍然收到此错误。作为记录,代码确实可以工作并且可以编译——react 对我的语法和组织感到满意。但是打字稿是否试图告诉我一些关于我使用组件作为道具的方式?有没有更合适的方法来做到这一点?谢谢阅读。

标签: javascriptreactjstypescriptreact-props

解决方案


检查这里的代码,这是类型不匹配的问题ReactElementvsFunctionalComponent

更新:

嘿,你能把它改成

const ChapterTemplate = ({
    data,
    map,
}: { data: any, map: FunctionComponent<MapProps>}) => { // change this to ReactElement
  return (<div>Hello world</div>);
}

const Chapter: FunctionComponent<ChapterProps> = (props) => {
    return <ChapterTemplate data={props.data} map={Map} />;
};

然后做<Map />

或者这样做

const ChapterTemplate = ({
    data,
    map,
}: { data: any, map: ReactElement}) => { // change this to ReactElement
  return (<div>Hello world</div>);
}

const Chapter: FunctionComponent<ChapterProps> = (props) => {
    return <ChapterTemplate data={props.data} map={<Map />} />;
};

推荐阅读