问题
I'm creating a higher-order component to wrap a component extending the interface:
interface ClickOutsideInterface {
onClickOutside: (e: Event) => void
}
The factory I've created expects a React.ComponentClass
implementing the ClickOutsideInterface
:
function clickOutside<P>(Component: React.ComponentClass<P> & ClickOutsideInterface){
return class ClickOutside extends React.Component<P, {}> {
/* on click outside invoke Component.onClickOutside */
render() {
return(<div><Component {...this.props} /></div>)
}
}
}
To test the factory, I've implement a Component extending the ClickOutsideInterface
class Test extends React.Component<TProps, TState> implements ClickOutsideInterface {
onClickOutside(event: Event): void {
this.setState({
closed: true
})
}
render(){
return(
<div>{this.state.closed}</div>
)
}
}
But when I use the component as an argument in the function clickOutside
:
const withClickOutside = clickOutside(Test)
I get the following type error for argument Test
:
Argument of type 'typeof Test' is not assignable to parameter of type 'ComponentClass & ClickOutsideInterface'. Type 'typeof Test' is not assignable to type 'ClickOutsideInterface'. Property 'onClickOutside' is missing in type 'typeof Test'.
Any ideas why Typescript believes I'm not implementing the interface in Test
?
回答1:
TypeScript says that you haven't implemented the interface your function requires of its argument because you indeed have not.
When you write
class A {
//...
}
You define two types and one value.
The value, which is named A
, is the class. It is the function that you call with new
to create objects.
The first type, which is also named A
, is the type of the objects that are created by calling the class function with new
as described above.
The second type is the type of that class function. Declaring a class doesn't automatically create a name for this type but the type exists none the less because all values have a type. This type is written typeof A
because it is the type of the value A
, the type of the class.
Therefore, depending on what you're trying to accomplish, you need to either
Pass an instance of Test
const withClickOutside = clickOutside(new Test);
Or change your function so that it takes an object matching the type of the class itself, and not the objects it creates
function clickOutside<P>(
Component: new () => React.ComponentClass<P> & ClickOutsideInterface
) {...}
I suspect it is the latter that you want in this case.
Lastly, while you may want it for documentation purposes which is a completely valid, I'd like to note that there's no reason to actually declare that your class even implements the interface at all. TypeScript is a structurally typed language and all interfaces are implemented by having compatible members.
来源:https://stackoverflow.com/questions/47001804/typescript-typeof-react-component-does-not-extend-interface-trouble-defining