kdojeteri
kdojeteri

Reputation: 805

Implementing interface. How to extend property type?

In my React project I have a couple components that share a similar shape (properties and methods). In order to keep things maintainable, I created a common interface for them:

interface IControl {
  props: {
    title: string;
  }
}

But whenever I implement this interface on a component whose props are a superset of IControl's, I get an error:

8:   props: {            ^ property `onClick`. Property not found in 
2:   props: {            ^ object type

Try it out

Full example source code:

interface IControl {
  props: {
    title: string;
  }
}

class FooComponent implements IControl {
  props: {
    title: string;
    onClick: () => void;
  }
}

Upvotes: 0

Views: 741

Answers (1)

Nat Mote
Nat Mote

Reputation: 4086

This is because objects in JS are mutable, and I could take an instance of IControl and assign props to it, without the props required by the implementing class. Here is the solution (it's a one character change):

interface IControl {
  +props: {
    title: string;
  }
}

class FooComponent implements IControl {
  props: {
    title: string;
    onClick: () => void;
  }
}

const x: IControl = new FooComponent();

x.props = {title: 'asdf'};

(x.props.title: string)

(try flow)

This makes use of property variance. You can see that it disallows the incorrect assignment, but it does allow an access of x.props.title.

Upvotes: 1

Related Questions