Chaim Friedman
Chaim Friedman

Reputation: 6253

How to constrain a type based on another type with flow?

Imagine I have a flow type like this.

type Sample = {
    someProp: "foo" | "bar";
    arr: Array<string | number>
}

The idea is that I would like to enforce the type of array based on the string value used for someProp. In other words, if say the type of someProp is "foo" I want the type of arr to be Array<string>, but if the type of someProp is "bar", I want the type of arr to be Array<number>.

I understand that my example's approach may be off, so I guess I am asking how I would do this at all. I was thinking about using generics somehow, but I just don't understand how to go about this at all.

Upvotes: 1

Views: 98

Answers (1)

Josh Story
Josh Story

Reputation: 21

using $Call utility type (https://flow.org/en/docs/types/utilities/#toc-call) you can constrain this relatively easily. It gets harder when you want to further genericize this but if you can use string literal values in your types then you should be ok

type Sample<T: "foo" | "bar"> = {
    someProp: T,
    arr: Array<Constrained<T>>
}

type Constrained<T: string> = $Call<("foo" => string) & ("bar" => number), T>

let x: Sample<"foo"> = {
  someProp: "foo",
  arr: ["hello", "no numbers", "here", 2]
}

let y: Sample<"bar"> = {
  someProp: "bar",
  arr: [1, 2, 3, "oops"]
}

Try Link

Upvotes: 2

Related Questions