1

我正在使用 Prismic、Gatsby 和 Typescript 构建一个站点。Prismic 的部分吸引力在于切片功能,它允许您创建更易于内容编辑器使用的动态内容部分。我有一个称为SliceZone映射页面上所有切片的组件:

切片区.tsx

import React from 'react';

import { ImageCta } from 'components/slices/call-to-action/image/ImageCta';
import { Columns } from 'components/slices/columns/Columns';
import { ContentBlock } from 'components/slices/content-block/ContentBlock';
import { Embed } from 'components/slices/embed/Embed';
import { TextHero } from 'components/slices/hero/text/TextHero';
import { Slider } from 'components/slices/slider/Slider';
import { Video } from 'components/slices/video/Video';

interface PageSlicesProps {
  slices: any;
}

const PageSlices = ({ slices }: PageSlicesProps) => {
  const sliceComponents = {
    hero: TextHero,
    slider: Slider,
    content_block: ContentBlock,
    video: Video,
    columns: Columns,
    embed: Embed,
    image_call_to_action: ImageCta,
  };

  return slices.map((slice: any, index: number) => {
    const SliceComponent = sliceComponents[slice.type];
    
    if (SliceComponent) {
      return <SliceComponent slice={slice} key={`slice-${slice.type}-${index}`} />;
    }
  }); 
};

interface SliceZoneProps {
  bodyContent: any;
}

export const SliceZone = ({ bodyContent }: SliceZoneProps) => <PageSlices slices={bodyContent.body} />;

我需要适当地输入所有内容。但是,我收到此错误SliceComponent,特别是sliceComponents[slice.type]

Element implicitly has an 'any' type because expression of type 'any' can't be used to index type '{ hero: ({ slice }: any) => Element; slider: ({ slice }: any) => Element; content_block: ({ slice }: any) => Element; video: ({ slice }: any) => Element; columns: ({ slice }: any) => Element; embed: ({ slice }: { ...; }) => Element; image_call_to_action: ({ slice }: any) => Element; }'.

我如何创建一个interface可以适当输入这个的?如果我的问题有点含糊,我很抱歉,我是 React 和 Typescript 的新手,所以语言对我来说有点过时了。

4

1 回答 1

0

问题是当您映射const sliceComponents =. 它缺少签名,因此返回类型是隐式的any。正如错误所说。

你可以通过说你有一个 React 类组件/函数组件的列表来明确说明吗?

const sliceComponentsMap: {
  [key: string]: typeof Component | FunctionComponent;
} 

|联合运算符。这表示它可以是这两种类型中的任何一种。


但我认为创建一个扩展 React Component 类的通用切片类会更好。

export interface sliceCommonProps {
  id: string;
}

// Interface for base slice props
export interface sliceProps<P> {
  sliceType: string;
  sliceData: P & sliceCommonProps; // This "&" joins the 'Generic' param P with the common props interface
}

export interface sliceState {}

// Base class with two generic params (P, S) for passing specific component props and state interfaces later
export class SliceComponent<
  P = { [key: string]: any },
  S = { [key: string]: any }
> extends Component<sliceProps<P>, sliceState> {}

并让您的切片组件扩展它。

export interface ImageCtaProps {
  imageUrl: string;
}

export class ImageCta extends SliceComponent<ImageCtaProps> {
  render() {
    const { id, imageUrl } = this.props.sliceData;
    return <div>{imageUrl}</div>;
  }
}

然后,当您将它们映射到它们的组件时,您可以说它们是 SliceComponent 类型。并且编译器现在知道组件应该具有正确的道具。

const sliceComponents: {[key: string]: typeof SliceComponent;} = {
   hero: TextHero,
   ...
};

slices.map((slice, index) => {
  const SliceComponent = sliceComponents[slice.type];
  return <SliceComponent sliceData={slice} sliceType={slice.type} />
  );
});

检查这个堆栈

于 2020-09-08T20:32:28.740 回答