Prismic Slices 的 Typescript 类型

Typescript types for Prismic Slices

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

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 的新手,所以到目前为止我对这门语言有点不适应。

问题出在 const sliceComponents = 的映射时。它缺少签名,因此 return 类型隐式为 any。 正如错误所说。

你可以明确地说你有一个 React class components/function 组件列表吗?

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

| 是一个 union 运算符。这表示它可以是这些类型中的任何一种。


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

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} />
  );
});

Check this stack