Reputation: 439
I have a BaseComponent which inherits from React.Component
. All other components in the app inherit from BaseComponent
. I need to type BaseComponent
such that other components inheriting from it are handled as React components by Flow. This is what I currently have:
class BaseComponent<P, S> extends React.Component<$Shape<P>, P, S> {
...
}
class OtherComponent extends BaseComponent {
props: {};
state: {}:
...
}
Here's a working example.
Flow correctly checks props, state, etc. in OtherComponent
.
In BaseComponent, however, I get obscure errors:
S: This type is incompatible with 'undefined. Did you forget to declare S?
P: This type is incompatible with 'undefined. Did you forget to declare P?
Did you forget to declare some incompatible instantiation of
S?: This type is incompatible with 'some incompatible instantiation of
S'
I'm struggling to understand the errors message. Any help would be greatly appreciated.
Upvotes: 3
Views: 1426
Reputation: 9438
In order to have my code work with a variable number of generic arguments, this is how I ended up typing the component:
export default class NewComponent<P, S = {}> extends Component<P, S> {
props: P
state: S
...
}
Upvotes: 0
Reputation: 439
After a large amount of experimentation, this what I ended up with. It appears to work correctly:
class BaseComponent<Props:Object, State, DefaultProps: $Shape<Props>> extends React.Component<DefaultProps, Props, State> {
static defaultProps: $Abstract<DefaultProps>;
props: Props;
state: $Abstract<State>;
}
The key was to define props/state/and defaultProps on baseComponent
in addition to passing the type params through to React.Components
. I'm not sure why this is necessary, but it does solve the issue.
Upvotes: 0
Reputation: 21
This works for me:
class BaseComponent<D, P, S> extends React.Component<D, P, S> {
static defaultProps: D
props: P
state: S
yourCustomFunction(): void
}
class You extends BaseComponent<any, any, any> {
--- component body ---
}
Upvotes: 2