Следуя этому руководству: https://reacttraining.com/react-router/web/example/auth-workflow.
Пытаемся воспроизвести код:
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route
{...rest}
render = {props =>
fakeAuth.isAuthenticated ? (
<Component {...props} />
) : (
<Redirect
to = {{
pathname: "/login",
state: { from: props.location }
}}
/>
)
}
/>
);
В TypeScript:
import * as React from 'react';
import { Route, RouterProps } from 'react-router';
interface Props extends RouterProps {
component: React.Component;
}
const PrivateRoute = ({ component: Component, ...rest }: Props) => {
return (
<Route
{...rest}
render = {(props) => <Component {...props} />}
/>
);
};
export default PrivateRoute;
Но он всегда терпел неудачу. Пробовал разные варианты. Тот, который я опубликовал в последний раз. Получающий:
Мне кажется, что мне нужно передать Generic для типа Component, но я не знаю как.
Обновлено:
Ближайшее решение на данный момент:
interface Props extends RouteProps {
component: () => any;
}
const PrivateRoute = ({ component: Component, ...rest }: Props) => {
return (
<Route
{...rest}
render = {(props) => <Component {...props} />}
/>
);
};
А потом:
<PrivateRoute component = {Foo} path = "/foo" />



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы хотите передать конструктор компонента, а не экземпляр компонента:
import * as React from 'react';
import { Route, RouteProps } from 'react-router';
interface Props extends RouteProps {
component: React.ComponentType;
}
const PrivateRoute = ({ component: Component, ...rest }: Props) => {
return (
<Route
{...rest}
render = {(props) => <Component {...props} />}
/>
);
};
export default PrivateRoute;
class Foo extends React.Component {
}
let r = <PrivateRoute component = {Foo} path = "/foo" />
Редактировать
Более полное решение должно быть общим и использовать RouteProps вместо RouterProps:
import * as React from 'react';
import { Route, RouteProps } from 'react-router';
type Props<P> = RouteProps & P & {
component: React.ComponentType<P>;
}
const PrivateRoute = function <P>(p: Props<P>) {
// We can't use destructuring syntax, because : "Rest types may only be created from object types", so we do it manually.
let rest = omit(p, "component");
let Component = p.component;
return (
<Route
{...rest}
render = {(props: P) => <p.component {...props} />}
/>
);
};
// Helpers
type Diff<T extends string, U extends string> = ({[P in T]: P } & {[P in U]: never } & { [x: string]: never })[T];
type Omit<T, K extends keyof T> = Pick<T, Diff<keyof T, K>>;
function omit<T, TKey extends keyof T>(value:T, ... toRemove: TKey[]): Omit<T, TKey>{
var result = Object.assign({}, value);
for(let key of toRemove){
delete result[key];
}
return result;
}
export default PrivateRoute;
class Foo extends React.Component<{ prop: number }>{
}
let r = <PrivateRoute component = {Foo} path = "/foo" prop = {10} />
@Oleg обновил решение, сделав его универсальным, и исправил использование RouterProps до RouteProps.
Спасибо, что уделили время этому и развернутому ответу. Однако это кажется излишним. Я обновил описание, указав наиболее близкий к цели код. Теперь стоит задача найти правильную подпись для component. Согласно github.com/ReactTraining/react-router/blob/master/packages/… - это просто функция. Отладчик указал его как () => Element, но это не работает.
@Oleg Если универсальная версия избыточна (я не думаю, что это обязательно, потому что вы будете использовать ее повторно, но это ваш выбор), почему первое решение не работает? Я включил для него полный код, он компилируется для меня. У вас есть проблемы с этим?
После нескольких часов и некоторого исследования вот решение, которое соответствует моим требованиям:
import * as React from 'react';
import { Route, RouteComponentProps, RouteProps } from 'react-router';
const PrivateRoute: React.SFC<RouteProps> =
({ component: Component, ...rest }) => {
if (!Component) {
return null;
}
return (
<Route
{...rest}
render = {(props: RouteComponentProps<{}>) => <Component {...props} />}
/>
);
};
export default PrivateRoute;
any;Я думаю, вы имели в виду export default PrivateRoute; в своей последней строке
Это похоже на движение в правильном направлении. Однако не знаю, как использовать
PrivateRouteв этом случае. Что-то вроде<PrivateRoute component = {Foo} path = "/foo" />выдает ошибку несоответствия свойств. Таким образом, либо один использует что-то отличное отReact.Component, либо предоставляет другойpropsпри использованииPrivateRoute.