routes.tsx:
(Note: I have modified @types/react-router to also export the type ReactComponents)
import * as React from 'react'
import { IndexRoute, Route, ReactComponents } from 'react-router'
import App from './App'
import MainComponent from './MainComponent'
import SidebarComponent from './SidebarComponent'
const components: ReactComponents = { // Type '{ main: typeof MainComponent; sidebar: typeof SidebarComponent; }' is not assignable to type 'RouteComponents'.
main: MainComponent,
sidebar: SidebarComponent
}
const routes = () => {
return (
<Route path="/" component={App}>
<IndexRoute components={components} /> // No error here.
<Route components={main: MainComponent, sidebar: SidebarComponent} /> // Same error as above
</Route>
)
}
export default routes
App.tsx
import * as React from 'react'
interface P { // Defining custom type argument
main: React.Component<any, any>,
sidebar: React.Component<any, any>
}
export default class App extends React.Component<P, null> { // using null is better than any when the Component does not use state
constructor(props: P) {
super(props)
}
public render() {
const { main, sidebar } = this.props
return (
<div>
{sidebar}
{main}
</div>
)
}
}
MainComponent.tsx:
import * as React from 'react'
interface S { // Defining my Type Argument...
query: string
}
export default class MainComponent extends React.Component<null, S> { // using null is better than any when the component does not use any props
constructor(props: null) {
super(props)
this.handleQueryChange = this.handleQueryChange.bind(this)
this.state = { query: '' }
}
public handleQueryChange(input: string) {
this.setState({ query: input })
}
public render() {
return (
<div>Content</div>
)
}
}
SidebarComponent.tsx
import * as React from 'react'
import { Link } from 'react-router'
export default class SidebarComponent extends React.Component<null, null> {
constructor(props: null) {
super(props)
}
public render() {
return (
<div>
<h3>Menu</h3>
<ul role="nav">
<li><Link to="">Something</Link></li>
<li><Link to="/add">Else</Link></li>
</ul>
</div>
)
}
}
Expected Behavior
React.Component<P, S> accepts two custom type arguments for prop and state, so react-router/typescript should be able to handle any sort of type arguments without a problem. The code will work fine if I use React.Component<any, any>.
Actual Behavior
But, react-routerRoute only accepts Components that have type arguments like React.Component<any, any>. When using my custom defined prop and state interfaces in place of any, any, I get the following error:
Type '{ main: typeof MainComponent; sidebar: typeof SidebarComponent; }' is not assignable to type 'RouteComponents'. Property 'sidebar' is incompatible with index signature. Type 'typeof SidebarComponent' is not assignable to type 'ReactType'. Type 'typeof SidebarComponent' is not assignable to type 'StatelessComponent'. Type 'typeof SidebarComponent' provides no match for the signature '(props: any, context?: any): ReactElement'
These errors go away if I simply change my Components to extend from React.Component<any, any>
Version
2.8.1
Test Case
Steps to reproduce
Use this code:
routes.tsx: (Note: I have modified
@types/react-router
to also export the typeReactComponents
)App.tsx
MainComponent.tsx:
SidebarComponent.tsx
Expected Behavior
React.Component<P, S>
accepts two custom type arguments for prop and state, soreact-router
/typescript should be able to handle any sort of type arguments without a problem. The code will work fine if I useReact.Component<any, any>
.Actual Behavior
But,
react-router
Route
only accepts Components that have type arguments likeReact.Component<any, any>
. When using my custom defined prop and state interfaces in place ofany, any
, I get the following error:These errors go away if I simply change my Components to extend from
React.Component<any, any>