首页 > 解决方案 > 如何为具有字符串作为键和 React SFC 作为值的对象包装器定义 TypeScript 类型?

问题描述

以下是表单组件

import React from 'react';
import { Elements } from '@helpers/ImportProxy';
import { mockApi } from '@constants/api';

type Props = {
  // formValues: any
};

type MapKindToComponentT = {
  [key: string]: React.SFC
}

/** @component */
export const Form: React.SFC<Props> = __props => {
  const renderQuestions = () =>
    mockApi.map(
      (question, index): React.ReactElement | undefined => {
        const mapKindToComponent: MapKindToComponentT = {
            radio:        Elements.RadioElement,
            text:         Elements.InputElement,
            email:        Elements.InputElement,
            url:          Elements.InputElement,
            checkbox:     Elements.CheckBoxElement,
            dropdown:     Elements.SelectElement,
            textarea:     Elements.TextareaElement,
        };
        if(mapKindToComponent[question.kind]) {
          const Element = mapKindToComponent[question.kind];
          return <Element key={index} question={question} />;
        }
      }
    );

  return (
    <form>
      {renderQuestions()}
      <div>
        <button type="submit">Submit</button>
      </div>
    </form>
  );
};

export default Form;

每个键的值mapKindToComponent是 React 功能组件。

以下是我得到的错误,因为它是当前定义的类型。与any.

类型错误:类型“FunctionComponent”不可分配给类型“FunctionComponent<{}>”。属性“propTypes”的类型不兼容。键入'弱验证映射 | undefined' 不可分配给类型 'WeakValidationMap<{}> | 不明确的'。类型“WeakValidationMap”不可分配给类型“WeakValidationMap<{}>”。类型“{}”不可分配给类型“道具”。TS2322

标签: javascriptreactjstypescriptjsxobject-literal

解决方案


解决方案

明确MapKindToComponentT接受任何类型的功能组件。

type MapKindToComponentT = {
  [key: string]: React.SFC<any>
}

解释

中定义的默认类型参数(描述 的参数Props)是.React.SFC@types/react{}

type SFC<P = {}> = FunctionComponent<P>;

如果一个组件需要一些更精确的类型作为它的 props,例如{ foo: string }

declare const SomeComponent: React.SFC<{ foo: string }>;

这样的组件将不能分配给React.SFC.

const MyComponent: React.SFC = SomeComponent;      // ⛔️ Compile-time error
const MyComponent: React.SFC<any> = SomeComponent; // ✅ OK

推荐阅读