Utility Types
Flow provides a set of utility types to operate on other types to create new types.
$Keys<T>
You can extract the type of the keys from an object type. Typically this will be a union of string literal types:
1const countries = {2 US: "United States",3 IT: "Italy",4 FR: "France"5};6
7type Country = $Keys<typeof countries>;8
9const italy: Country = 'IT'; // Works10const nope: Country = 'nope'; // Error! 10:23-10:28: Cannot assign `'nope'` to `nope` because property `nope` is missing in object literal [1]. [prop-missing]
In the example above, the type of Country is equivalent to type Country = 'US' | 'IT' | 'FR', but Flow was able to extract it from the keys of countries.
If you want to create an enum type, Flow Enums might be a better fit for your use-case.
$Values<T>
$Values<T> represents the union type of all the value types of the enumerable properties in an object type,
or the elements of an array or tuple type (support for arrays and tuples in Flow version ≥0.240):
1type Props = {2 name: string,3 age: number,4};5
6// The following two types are equivalent:7type PropValues = string | number;8type Prop$Values = $Values<Props>;9
10const name: Prop$Values = 'Jon'; // Works11const age: Prop$Values = 42; // Works12const fn: Prop$Values = true; // Error! 12:25-12:28: Cannot assign `true` to `fn` because: [incompatible-type] Either boolean [1] is incompatible with string [2]. Or boolean [1] is incompatible with number [3].
For arrays and tuples:
1type Arr = Array<string>;2type Str = $Values<Arr>; //=> string3's' as Str; // OK4
5type Tup = [1, 2];6type Num = $Values<Tup>; //=> 1 | 271 as Num; // OKNote that using $Values on the typeof an object or array literal will result in a type more general than you might expect:
1const obj = {2 foo: 1,3 bar: 2,4};5
6function acceptsValues(x: $Values<typeof obj>) { /* ... */ }7
8acceptsValues(1); // Works9acceptsValues(3); // Works, because the type was interpreted as `number`.This behavior changes if you use Object.freeze on the object literal expression:
1const obj = Object.freeze({2 foo: 1,3 bar: 2,4});5
6function acceptsValues(x: $Values<typeof obj>) { /* ... */ }7
8acceptsValues(1); // Works9acceptsValues(3); // Error! Because the type was interpreted as `1 | 2`. 9:15-9:15: Cannot call `acceptsValues` with `3` bound to `x` because number [1] is incompatible with `$Values` [2]. [incompatible-type]
If you want to create an enum type, Flow Enums might be a better fit for your use-case.
$ReadOnly<T>
$ReadOnly<T> is a type that represents the read-only version of a given object type
or tuple type T (support for tuples is for Flow ≥0.212).
A read-only object type is an object type whose keys are all read-only.
Similarly, a read-only tuple is one where each element is read-only.
This means that the following are equivalent:
1type ReadOnlyObj = {2 +key: number, // read-only field, marked by the `+` annotation3};4type ReadOnlyTuple = [+foo: number];→
1type ReadOnlyObj = $ReadOnly<{2 key: number,3}>;4type ReadOnlyTuple = $ReadOnly<[number]>;This is useful when you need to use a read-only version of an object type you've already defined, without manually having to re-define and annotate each key as read-only. For example:
1type Props = {2 name: string,3 age: number,4};5
6type ReadOnlyProps = $ReadOnly<Props>;7
8function render(props: ReadOnlyProps) {9 const {name, age} = props; // Works10 props.age = 42; // Error! 11}10:9-10:11: Cannot assign `42` to `props.age` because property `age` is not writable. [cannot-write]
Additionally, other utility types, such as spread, may strip any read/write annotations, so $ReadOnly<T> is a handy way to quickly make the object read-only again after operating on it:
1type Obj = {2 +key: number,3};4
5type MappedObj = $ReadOnly<{...Obj, foo: string}> // Still read-onlyThe $ReadOnly utility works on object and tuple types.
If you want to make other types read-only, you can use one of the following:
Array<T>->$ReadOnlyArray<T>Set<T>->$ReadOnlySet<T>Map<K, V>->$ReadOnlyMap<K, V>WeakSet<T>->$ReadOnlyWeakSet<T>WeakMap<K, V>->$ReadOnlyWeakMap<K, V>
Partial<T> ≥0.201
This utility converts all of an object or interface's named fields to be optional,
while maintaining all the object's other properties (e.g. exactness, variance).
Use this utility instead of $Shape.
Since Flow ≥0.212, it also converts all of a tuple type's elements to be optional.
Example for objects:
1type Person = {2 name: string,3 age: number,4};5type PartialPerson = Partial<Person>;6// Above equivalent to `{name?: string, age?: number}`7
8const a: PartialPerson = {}; // OK9const b: PartialPerson = {name: 'George'}; // OK10const c: PartialPerson = {name: 'George', age: 123}; // OK11
12c as Person; // ERROR: `PersonDetails` is not a `Person` (unlike with `$Shape`) 12:1-12:1: Cannot cast `c` to `Person` because properties `age` and `name` of `{age?: number, name?: string}` [1] are not exactly the same as those of `Person` [2]. [incompatible-type] The above-mentioned two types must be the same because properties `age` and `name` are invariantly typed. To fix the error, - Either make `{age?: number, name?: string}` [3] and `Person` [3] exactly the same - Or make properties `age` and `name` in `Person` [2] readonly. See https://flow.org/en/docs/faq/#why-cant-i-pass-a-string-to-a-function-that-takes-a-string-number.
For tuples:
1type AllRequired = [number, string];2[] as Partial<AllRequired>; // OK: like `[a?: number, b?: string]` nowA object or tuple of type T cannot be supplied to Partial<T>, due to mutability. You can resolve this by making the object read-only:
1type Person = {2 name: string,3 age: number,4};5
6const person: Person = {name: 'George', age: 123};7
8function noPerson(o: Partial<Person>) {9 // Can mutate:10 o.name = undefined;11}12noPerson(person); // Error! 13
14function okPerson(o: $ReadOnly<Partial<Person>>) {15 // Can't mutate - it's read-only!16}17okPerson(person); // Works12:10-12:15: Cannot call `noPerson` with `person` bound to `o` because properties `age` and `name` of `Person` [1] are not exactly the same as those of `{age?: number, name?: string}` [2]. [incompatible-type] The above-mentioned two types must be the same because properties `age` and `name` are invariantly typed. To fix the error, - Either make `Person` [3] and `{age?: number, name?: string}` [3] exactly the same - Or make properties `age` and `name` in `Person` [2] readonly. See https://flow.org/en/docs/faq/#why-cant-i-pass-a-string-to-a-function-that-takes-a-string-number.
Note: Up until Flow version 0.201, this utility type was named $Partial.
Required<T> ≥0.201
The Required utility type is the opposite of Partial:
it converts all of an object or interface’s optional fields to be required.
Since Flow ≥0.212, it also converts all of a tuple type's elements to be required.
Example for objects:
1type PartialPerson = {2 name?: string,3 age?: number,4};5type Person = Required<PartialPerson>;6// Above equivalent to `{name: string, age: number}`7
8const a: Person = {name: 'George', age: 123}; // OK9const b: Person = {age: 123}; // ERROR: missing `name` property 9:19-9:28: Cannot assign object literal to `b` because property `name` is missing in object literal [1] but exists in `PartialPerson` [2]. [incompatible-type]
For tuples:
1type AllOptional = [a?: number, b?: string];2[] as Required<AllOptional>; // ERROR: like `[a: number, b: string]` now 2:1-2:2: Cannot cast array literal to required of `AllOptional` because empty array literal [1] has 0 elements but `AllOptional` [2] has 2 elements. [invalid-tuple-arity]