Обновление 2
Основываясь на втором комментарии artem , я смог решить мою проблему, изменив
component: <TestRoute />
до
component: TestRoute
Обновление
Основываясь на комментарии artem , я изменил свой код следующим образом, и ошибка, с которой я столкнулся, исчезла, но заменена новой, на этот раз в конструкторе, которому я назначаю свойство компонента:
ОШИБКА в [at-loader] ./src/ts/components/app/StandardRouter.tsx:34:13
TS2322: тип «Элемент» нельзя назначить типу «ComponentClass | FunctionComponent.
Тип «Элемент» не может быть назначен типу «FunctionComponent».
Тип «Элемент» не обеспечивает совпадения для подписи »(реквизиты: любой, контекст ?: любой): ReactElement | нуль».
StandardRouter.tsx
// React router component. Connects all routes to the application.
import * as React from 'react';
import { connect } from 'react-redux';
import { Route, Switch, withRouter } from 'react-router-dom';
import { ConnectedRouter } from 'connected-react-router';
import { IntlProvider } from 'react-intl';
import _forEach from 'lodash/forEach';
import _find from 'lodash/find';
import { History, createHashHistory } from 'history';
import { connectRouter } from 'connected-react-router';
import reducerRegistry from '../../api/private/core/reducer-registry';
import routeRegistry from '../../api/private/core/route-registry';
import RouteObject from '../../interfaces/route-object';
import TestRoute from '../test/test-route';
class StandardRouter extends React.Component {
constructor(props: object) {
super(props);
this._history = createHashHistory();
reducerRegistry.register({
name: 'router',
key: 'cb3dceb0-367b-4c2a-a0fb-a8d8671283e2',
reducer: connectRouter(this._history)
});
routeRegistry.setChangeListener(() => {
if (this._isMounted) {
this.forceUpdate();
} else if (!this._isMounted && !this._doUpdate) {
this._doUpdate = true;
}
});
routeRegistry.register({
key: '90e8246f-96a6-49a5-920a-a2cf0d347fcd',
component: <TestRoute />, // <-- New error here
paths: '/',
text: 'Test 123'
});
}
componentDidMount(): void {
this._isMounted = true;
if (this._doUpdate) {
this.forceUpdate();
}
}
private _history: History;
private _isMounted: boolean = false;
private _doUpdate: boolean = false;
chooseRender(path: string, Comp: React.ComponentType): React.ReactNode {
return <Comp />;
}
// Creates Route objects based on routes collection from registry
renderPages(): React.ReactNode[] {
const routes: React.ReactNode[] = [];
const loadedRoutes: RouteObject[] = routeRegistry.getRoutes();
_forEach(loadedRoutes, page => {
const Component = withRouter(
connect<any, any, any>(() => ({
pageid: page.pageId
}))(page.component) // <-- Error on this line, on page.component.
);
if (Array.isArray(page.paths)) {
// Multiple paths available for a single route. For example "/" and "/Home" for the
// home page.
_forEach(page.paths, inner => {
routes.push(<Route key={inner} path={inner} render={() => this.chooseRender(inner, Component)} />);
});
} else {
// A single path for a route.
routes.push(
<Route
key={page.paths}
path={page.paths}
render={() => this.chooseRender(page.paths as string, Component)}
/>
);
}
});
return routes;
}
render() {
return (
<div style={{ zIndex: -1 }}>
<IntlProvider locale="en">
<div>
<ConnectedRouter history={this._history}>
<Switch>{this.renderPages()}</Switch>
</ConnectedRouter>
</div>
</IntlProvider>
</div>
);
}
}
export default StandardRouter;
маршрутный object.ts
type RouteObject = {
key: string;
component: React.ComponentType<any>;
paths: string | string[];
text: string;
shortText?: string;
index?: number;
pageId?: string;
icon?: React.ReactNode;
};
export default RouteObject;
тест-route.tsx
import React from 'react';
class TestRoute extends React.PureComponent {
render() {
return <div />;
}
}
export default TestRoute;
Опять же, я не уверен, почему я не могу назначить свойство PureComponent свойству ComponentType. Заранее спасибо!
Оригинальный вопрос ниже
Я работаю над преобразованием нашего javascript-приложения в TypeScript и столкнулся с проблемой. Я все еще пытаюсь понять все сложности TypeScript.
Мы динамически подключаем наши маршруты к избыточному и маршрутизатору во время выполнения. Это работает правильно, когда в JavaScript, но так как я преобразовал его в TypeScript, у меня возникли проблемы с его компиляцией. Я получаю ошибку
ОШИБКА в [at-loader] ./src/ts/components/app/StandardRouter.tsx:63:21
TS2345: Аргумент типа 'ReactNode' не может быть назначен параметру типа 'ComponentType'.
Тип 'undefined' нельзя назначить типу 'ComponentType'.
Я вижу, что ошибка вызвана неверным типом, но я не уверен, почему.
StandardRouter.tsx
// React router component. Connects all routes to the application.
import * as React from 'react';
import { connect } from 'react-redux';
import { Route, Switch, withRouter } from 'react-router-dom';
import { ConnectedRouter } from 'connected-react-router';
import { IntlProvider } from 'react-intl';
import _forEach from 'lodash/forEach';
import _find from 'lodash/find';
import { History, createHashHistory } from 'history';
import { connectRouter } from 'connected-react-router';
import reducerRegistry from '../../api/private/core/reducer-registry';
import routeRegistry from '../../api/private/core/route-registry';
import RouteObject from '../../interfaces/route-object';
import TestRoute from '../test/test-route';
class StandardRouter extends React.Component {
constructor(props: object) {
super(props);
this._history = createHashHistory();
reducerRegistry.register({
name: 'router',
key: 'cb3dceb0-367b-4c2a-a0fb-a8d8671283e2',
reducer: connectRouter(this._history)
});
routeRegistry.setChangeListener(() => {
if (this._isMounted) {
this.forceUpdate();
} else if (!this._isMounted && !this._doUpdate) {
this._doUpdate = true;
}
});
routeRegistry.register({
key: '90e8246f-96a6-49a5-920a-a2cf0d347fcd',
component: <TestRoute />,
paths: '/',
text: 'Test 123'
});
}
componentDidMount(): void {
this._isMounted = true;
if (this._doUpdate) {
this.forceUpdate();
}
}
private _history: History;
private _isMounted: boolean = false;
private _doUpdate: boolean = false;
chooseRender(path: string, Comp: React.ComponentType): React.ReactNode {
return <Comp />;
}
// Creates Route objects based on routes collection from registry
renderPages(): React.ReactNode[] {
const routes: React.ReactNode[] = [];
const loadedRoutes: RouteObject[] = routeRegistry.getRoutes();
_forEach(loadedRoutes, page => {
const Component = withRouter(
connect(() => ({
pageid: page.pageId
}))(page.component) // <-- Error on this line, on page.component.
);
if (Array.isArray(page.paths)) {
// Multiple paths available for a single route. For example "/" and "/Home" for the
// home page.
_forEach(page.paths, inner => {
routes.push(<Route key={inner} path={inner} render={() => this.chooseRender(inner, Component)} />);
});
} else {
// A single path for a route.
routes.push(
<Route
key={page.paths}
path={page.paths}
render={() => this.chooseRender(page.paths as string, Component)}
/>
);
}
});
return routes;
}
render() {
return (
<div style={{ zIndex: -1 }}>
<IntlProvider locale="en">
<div>
<ConnectedRouter history={this._history}>
<Switch>{this.renderPages()}</Switch>
</ConnectedRouter>
</div>
</IntlProvider>
</div>
);
}
}
export default StandardRouter;
маршрутный object.ts
type RouteObject = {
key: string;
component: React.ReactNode;
paths: string | string[];
text: string;
shortText?: string;
index?: number;
pageId?: string;
icon?: React.ReactNode;
};
export default RouteObject;
тест-route.tsx
import React from 'react';
class TestRoute extends React.PureComponent {
render() {
return <div />;
}
}
export default TestRoute;
Есть ли что-то, что могло бы вызвать это? Я не уверен, почему он не использует ReactNode.