alden
alden

Reputation: 439

How do Inherit from custom React Component without losing flow type information?

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:

  1. S: This type is incompatible with 'undefined. Did you forget to declare S?

  2. P: This type is incompatible with 'undefined. Did you forget to declare P?

  3. Did you forget to declare some incompatible instantiation ofS?: This type is incompatible with 'some incompatible instantiation ofS'

I'm struggling to understand the errors message. Any help would be greatly appreciated.

Upvotes: 3

Views: 1426

Answers (3)

Evan Siroky
Evan Siroky

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

alden
alden

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

Skopi
Skopi

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

Related Questions