Flow: How to use similar type for redux state and react state

Created on 2 Jan 2017  路  2Comments  路  Source: facebook/flow

Hello.

I have a type:

type Patient = {
  id: number,
  name: string
};

I use this type in Redux's reducers, for example:

// My patients reducer
function patients(state: Array<?Patient> = [], action: Object) { ... }

I also need to use this type in a Form component I use to insert patients. Just like:

class Form extends Component {
  state: Patient
  constructor(props) {
    super(props);
    this.state = {
      id: 0,
      name: '',
      errors: {}
    }
  // ...
}

Of course this don't work because Patient type has no errors property. Just like flux says:

property `errors` of object literal Property not found in Patient

But I don't want to create another type for the Form's state with the same id and name properties plus the errors property. I want to somehow _extend_ the Patient type to use in the Form state but keeping the errors property.

I had a research in the web and found that maybe interfaces can suit my needs, but if I try to declare the Patient type as an interface, the same error occurs.

Is there some technique to do that?

Most helpful comment

I presume that because this is a form of some sort that that's the reason you're not just reading the Patient stuff off the component props.

You could put the Patient object in a prop on the Component's state:

type OwnState = {
  patient: Patient,
  // or whatever type your `errors` prop has.
  errors: { [errorName: string]: string }
};

class Form extends Component {
  state: OwnState
  constructor(props) {
    super(props);
    this.state = {
      patient: {
        id: 0,
        name: '',
      },
      errors: {}
    }
  // ...
}

Though that presumes you're not using something which expects those props to be directly on this.state.

Failing that, does the & (Intersection) op work?

type OwnState = Patient & {
  // or whatever type your `errors` prop has.
  errors: { [errorName: string]: string }
};

class Form extends Component {
  state: OwnState
  constructor(props) {
    super(props);
    this.state = {
      id: 0,
      name: '',
      errors: {}
    }
  // ...
}

All 2 comments

I presume that because this is a form of some sort that that's the reason you're not just reading the Patient stuff off the component props.

You could put the Patient object in a prop on the Component's state:

type OwnState = {
  patient: Patient,
  // or whatever type your `errors` prop has.
  errors: { [errorName: string]: string }
};

class Form extends Component {
  state: OwnState
  constructor(props) {
    super(props);
    this.state = {
      patient: {
        id: 0,
        name: '',
      },
      errors: {}
    }
  // ...
}

Though that presumes you're not using something which expects those props to be directly on this.state.

Failing that, does the & (Intersection) op work?

type OwnState = Patient & {
  // or whatever type your `errors` prop has.
  errors: { [errorName: string]: string }
};

class Form extends Component {
  state: OwnState
  constructor(props) {
    super(props);
    this.state = {
      id: 0,
      name: '',
      errors: {}
    }
  // ...
}

Wow! Nice. The first solution looks good but to avoid refactoring my entire Form component I will stick with the second solution. I works great. :D

Thank you very much, @joedski.

Was this page helpful?
0 / 5 - 0 ratings