Передача реквизитов типа union для реагирования на дочерний компонент, для которого требуется один из типов в union - PullRequest
0 голосов
/ 21 мая 2018

В Typescript + Реагировать.У меня есть два компонента (модули) с определенными типами, указанными с помощью интерфейса.Кроме того, у меня есть один родительский компонент, который принимает массив с объединением, заданным как props.

Дочерние компоненты:

Модуль один

interface IModuleOneProps {
  moduleOneSpecificProp: string;
  module_type: sting;
  commonProp: string;
}

const ModuleOne: React.SFC<IModuleOneProps> = props => {
  return (
    <p>{moduleOneSpecificProp + " " + commonProp}</p>
  );
};

export default ModuleOne;

Модуль два

interface IModuleTwoProps {
  moduleTwoSpecificProp: string;
  module_type: sting;
  commonProp: string;
}

const ModuleTwo: React.SFC<IModuleTwoProps> = props => {
  return (
    <p>{moduleTwoSpecificProp + " " + commonProp}</p>
  );
};

export default ModuleTwo;

Компонент контейнера, который содержит массив модулей, которые могут быть обоих типов:

interface IContainerModuleProps {
modules: Array<
    IModuleOneProps | IModuleTwoProps
  >;
}

class ContainerModule extends React.Component<IContainerModuleProps> {

  public render() {
    const module = this.props.modules[1];
    switch (module.module_type) {
      case 'module_one':
        return <ModuleOne {...module} />;
      case 'module_two':
        return <ModuelTwo {...module} />;
    }
  }
}

Но TypeScript победил 'Позвольте мне распространять module при рендеринге компонентов.Он жалуется на типы.

Type '{ commonProp: string; moduleOneSpecificProp: string; }' is not assignable to type 'IntrinsicAttributes & IModuleOneProps & { children?: ReactNode; }'.
  Type '{ commonProp: string; moduleTwoSpecificProp: string; }' is not assignable to type 'IntrinsicAttributes & IModuleOneProps & { children?: ReactNode; }'.
    Property 'moduleOneSpecificProp' is missing in type '{ commonProp: string; moduleTwoSpecificProp: string; }'.

Есть ли быстрое исправление, которого я здесь не вижу?Или мне нужно перестроить объект prop (module) перед передачей его дочернему компоненту?

1 Ответ

0 голосов
/ 21 мая 2018

Вам необходимо определить свойство module_type как строковый литерал (строковый тип, который может иметь только одно значение), если вы сделаете это, тогда switch правильно введет значение guard:

interface IModuleOneProps {
    moduleOneSpecificProp: string;
    commonProp: string;
    module_type: "module_one"
}
interface IModuleTwoProps {
    moduleTwoSpecificProp: string;
    commonProp: string;
    module_type: "module_two"
}
interface IContainerModuleProps {
    modules: Array<
    IModuleOneProps | IModuleTwoProps
    >;
}

public render() {
    const module = this.props.modules[1];
    switch (module.module_type) {
        case 'module_one':
            return <ModuleOne {...module} />;
        case 'module_two':
            return <ModuleTwo {...module} />;
    }
}

Также вполне возможно использовать перечисление для строковых литералов, чтобы избежать зависимости от магических строк:

enum MODULE_NAME {
  MODULE_ONE,
  MODULE_TWO
}

А затем использовать MODULE_NAME.MODULE_ONE как на интерфейсе, так и в методе рендеринга.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...