Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FlowType: Inheritance of Types (Type A is a subset of type B ...)

Since the release of Flow 42, you could use object type spread. type TypeB = { ...TypeA }; 🎉

I suppose this is really beginner type of question about FlowType, but I really couldn't find the answer to satisfy me.

Let's presume I have this types

type A = {
 x: number
}

type B = {
 y: string
}

and now I want to have another type based on the type A and B, something like this:

type C = {
 ...A,
 ...B,
 z: boolean
}

which IMHO should be interpreted like:

type C = {
  x: number,
  y: string,
  z: boolean
}

But this obviously doesn't work.

Could you give me some advice or the best practice about this? Thanks a lot.

like image 943
jukben Avatar asked Feb 16 '17 18:02

jukben


2 Answers

This is a common feature request and it is actually on the way. Here's a commit that implements parsing for type spread. I'm not sure what the timeline is for this feature but I believe there is still ongoing work for it.

For now, you can use intersection types in some cases (though they weren't really designed for this use case and can lead to confusing problems):

type C = A & B & {
  z: boolean
}

You can, of course, also just choose to duplicate the properties for now. It is definitely the simplest thing to do although I agree it's a bit unpalatable.

like image 164
Nat Mote Avatar answered Nov 04 '22 18:11

Nat Mote


I've verified the spread is working as you would expect, intersections had me all over the place. Here is a short playground that shows flow type intersection failing to make a prop optional, whereas spread works.

Sample code for posterity:

// @flow

export type Affiliation = {
  id: string,
}

export type Address = {
  address1: string,
}


export type BaseContact = {
  id?: string,
  addresses: Array<Address>,
  affiliations?: Array<Affiliation>,
}

type C = BaseContact & {
  addresses: Array<Address>,
}

type CC = {
  ...BaseContact,
  addresses?: Array<Address>,
}

type CCI = BaseContact & {
  addresses?: Array<Address>,
}


class X {}

const c: C = new X() // fails
const cc: CC = new X() // fails
const cci: CCI = new X() // works
like image 29
kross Avatar answered Nov 04 '22 18:11

kross