Как определить тип TypeScript для обертки объекта, которая имеет строку в качестве ключа и React SFC в качестве значения? - PullRequest
0 голосов
/ 06 марта 2019

Ниже приведен компонент формы

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' несовместимыми. Тип 'WeakValidationMap | undefined 'нельзя назначить типу' WeakValidationMap <{}> | не определено. Тип «WeakValidationMap» нельзя назначить типу «WeakValidationMap <{}>». Тип «{}» нельзя назначить типу «Реквизит». TS2322

1 Ответ

2 голосов
/ 06 марта 2019

Решение

Укажите, что MapKindToComponentT принимает компоненты функций любого вида.

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

Объяснение

Параметр типа по умолчанию (тот, который описывает Props) для React.SFC, определенный в @types/react, равен {}.

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

Если компонент ожидает некоторый более точный тип в качестве своего реквизита, например { 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
...