Создание компонента более высокого порядка для взаимодействия react-relay и react-router с TypeScript

Хорошо, мой монстр Франкенштейна вышел из-под контроля, и мне осталось вырвать не так уж много волос, так что любая помощь приветствуется.

Я пытаюсь получить очень простую настройку приложения, работающую с React, React-Router, React-Relay и Typescript. У меня на самом деле все это работает, но при этом выдает несколько неприятных ошибок Typescript, которые я хотел бы исправить.

Таким образом, базовая установка react-router + react-relay имитирует официальный подход react-relay, найденный здесь: https://medium.com/@cpojer/relay-and-routing-36b5439bad9

К сожалению, при переводе этого на TypeScript и использовании импортированных определений типов для ретрансляции реакции через типизацию (и мне очень не пришлось бы изменять импортированные определения типов); Route определил свойства и объекты TypeScript для передачи свойств home и queries компоненту Route.

Прошу прощения за то, что выложил сюда свой код, но он понадобится вам, чтобы полностью оценить проблему.

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Router, Route, browserHistory } from 'react-router';
import * as Relay from 'react-relay';
import MainApp from './components/MainApp';

const createRelayContainer: any = function createRelayContainer (Component: new() => React.Component<any, any>, props: any): JSX.Element {
  if (Relay.isContainer(Component)) {
    // construct the RelayQueryConfig from the route and the router props
    const { name, queries } = props.route;
    const { params } = props;

    return (
      <Relay.RootContainer
        Component={Component}
        renderFetched={(data: any) : any => <Component {...props} {...data} /> }
        route={{name, params, queries}}
       />
    );
  }
  return <Component {...props} />;
};

const homeQueries: any = {
  viewer: (): Relay.QLExpression => Relay.QL`
    query {
      viewer
    }`,
};

ReactDOM.render(
  <Router
    history={ browserHistory }
    createElement={createRelayContainer}>
    <Route>
      <Route
        name='home'
        path='/'
        component={MainApp}
        queries={homeQueries}
      />
    </Route>
  </Router>,
  document.getElementById('root'));
;

Как я уже сказал, это на самом деле работает, как и ожидалось, но проблема в том, что интерфейс реактивного маршрутизатора для Route не имеет name или queries, поэтому TypeScript выдает ошибки.

Я уверен, что есть несколько разных подходов к решению этой проблемы, но я понятия не имею, что было бы лучше всего в этом сценарии.

(Может быть полезна некоторая базовая информация о версии: TypeScript 1.8.10, React 15, React-Router 2.4, React-Relay 0.8)


person Matt Martin    schedule 08.05.2016    source источник


Ответы (1)


Хорошо, самый простой ответ здесь — просто добавить к импортированным определениям реактивного маршрутизатора через слияние пространств имен (я не знал, что Typescript позволяет вам это делать).

Для тех, кому интересно, просто добавьте overrides.d.ts (или назовите его как хотите) и добавьте к интерфейсу RouteProps:

declare namespace ReactRouter {
  interface RouteProps {
    name?: string;
    queries?: any;
  }
}

Честно говоря, может быть более умный способ обойти все это, но это самый простой и он работает.

Эх, прошли часы моей жизни...

person Matt Martin    schedule 10.05.2016