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; // OK
Note 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-call]
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-only
The $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 undefined [1] is incompatible with number [1] in property `age`. [incompatible-cast]12:1-12:1: Cannot cast `c` to `Person` because undefined [1] is incompatible with string [1] in property `name`. [incompatible-cast]
For tuples:
1type AllRequired = [number, string];2[] as Partial<AllRequired>; // OK: like `[a?: number, b?: string]` now
A 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); // Works
12:10-12:15: Cannot call `noPerson` with `person` bound to `o` because undefined [1] is incompatible with number [1] in property `age`. This property is invariantly typed. See https://flow.org/en/docs/faq/#why-cant-i-pass-a-string-to-a-function-that-takes-a-string-number. [incompatible-call]12:10-12:15: Cannot call `noPerson` with `person` bound to `o` because undefined [1] is incompatible with string [1] in property `name`. This property is invariantly typed. See https://flow.org/en/docs/faq/#why-cant-i-pass-a-string-to-a-function-that-takes-a-string-number. [incompatible-call]
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]. [prop-missing]
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]
ReturnType<F>
≥0.209
This utility type extracts the return type from a given function type.
1declare function f(s: string, n: number): boolean;2type Bool = ReturnType<typeof f>;3true as Bool;41 as Bool; // Error: number is not boolean
4:1-4:1: Cannot cast `1` to `Bool` because number [1] is incompatible with boolean [2]. [incompatible-cast]
Parameters<F>
≥0.209
This utility type extracts the parameter types from a given function type into a tuple type.
1declare function f(s: string, n: number): boolean;2type Tuple = Parameters<typeof f>; // Evaluates to [string, number]3's' as Tuple[0];41 as Tuple[1];5false as Tuple[2]; // Error: tuple type only has two elements
5:16-5:16: Cannot access number literal `2` on `Tuple` because tuple type [1] only has 2 elements, so index 2 is out of bounds. [invalid-tuple-index]
Exclude<T, U>
≥0.209
This utility type excludes all subtypes of U
from T
.
1type T = Exclude<1 | 2 | 3 | 4, 1 | 3>; // evaluates to 2 | 421 as T; // error 32 as T; // ok43 as T; // error 54 as T; // ok
2:1-2:1: Cannot cast `1` to `T` because number [1] is incompatible with `Exclude` [2]. [incompatible-cast]4:1-4:1: Cannot cast `3` to `T` because number [1] is incompatible with `Exclude` [2]. [incompatible-cast]
Extract<T, U>
≥0.209
This utility type retains only subtypes of U
from T
.
1declare class Car {}2declare class Animal {}3declare class Dog extends Animal {}4declare class Cat extends Animal {}5type T = Extract<Car | Dog | Cat, Animal>; // evaluates to Dog | Cat6new Car() as T; // error 7new Dog() as T; // ok8new Cat() as T; // ok
6:1-6:9: Cannot cast `new Car()` to `T` because: [incompatible-cast] Either `Car` [1] is incompatible with `Dog` [2]. Or `Car` [1] is incompatible with `Cat` [3].
ThisParameterType<F>
≥0.209
This utility type extracts the type of the this
parameter of a given function type.
1type T = ThisParameterType<(this: number, bar: string) => void>; // Evaluates to number2'1' as T; // error 32 as T; // ok
2:1-2:3: Cannot cast `'1'` to `T` because string [1] is incompatible with number [2]. [incompatible-cast]
OmitThisParameter<F>
≥0.209
This utility type removes the this
parameter from a given function type.
1type HasThisParamFun = (this: number, bar: string) => void;2type NoThisParamFun = OmitThisParameter<HasThisParamFun> // Evaluates to (bar: string) => void3declare const hasThisParam: HasThisParamFun;4declare const noThisParam: NoThisParamFun;5
6hasThisParam(''); // error: global object is not number 7noThisParam(''); // ok: no this type requirement
6:1-6:12: Cannot call `hasThisParam` because global object [1] is incompatible with number [2]. [incompatible-call]
Pick<O, Keys>
≥0.211
This utility type allows you to generate an object type using a subset of the fields from another object type.
1type O = {foo: number, bar: string, baz: boolean};2type FooAndBar = Pick<O, 'foo' | 'bar'>;3
4declare const fooAndBar: FooAndBar;5fooAndBar.baz; // error: baz is missing 6fooAndBar.foo as number; // ok7fooAndBar.bar as string; // ok
5:11-5:13: Cannot get `fooAndBar.baz` because property `baz` (did you mean `bar`?) is missing in `Pick` [1]. [prop-missing]
Omit<O, Keys>
≥0.211
This utility type allows you to generate an object type by omitting the specified fields from another object type.
1type O = {foo: number, bar: string, baz: boolean};2type JustBaz= Omit<O, 'foo' | 'bar'>;3
4declare const justBaz: JustBaz;5justBaz.baz as boolean; // ok6justBaz.foo; // error: missing foo 7justBaz.bar; // error: missing bar
6:9-6:11: Cannot get `justBaz.foo` because property `foo` is missing in `Omit` [1]. [prop-missing]7:9-7:11: Cannot get `justBaz.bar` because property `bar` (did you mean `baz`?) is missing in `Omit` [1]. [prop-missing]
Record<Keys, Type>
≥0.211
This utility type allows you to generate an object type from a union of keys with the given
Type
for each field.
1type NumberRecord = Record<'foo' | 'bar', number>;2declare const numberRecord: NumberRecord;3numberRecord.foo as number; // ok4numberRecord.bar as number; // ok5numberRecord.baz; // error
5:14-5:16: Cannot get `numberRecord.baz` because property `baz` (did you mean `bar`?) is missing in `Record` [1]. [prop-missing]
Note that Record
is different than using an indexer:
1type NumberRecord = Record<'foo' | 'bar', number>;2type IndexedObject = {['foo' | 'bar']: number};3
4// Record uses explicit fields, which means they are all required5const rec: NumberRecord = {}; // error 6// Indexers do not have this same requirement7const idx: IndexedObject = {}; // no error
5:27-5:28: Cannot assign object literal to `rec` because property `bar` is missing in object literal [1] but exists in `Record` [2]. [prop-missing]5:27-5:28: Cannot assign object literal to `rec` because property `foo` is missing in object literal [1] but exists in `Record` [2]. [prop-missing]
$Exact<T>
You can use $Exact
to make an inexact object type exact:
1type InexactUser = {name: string, ...};2type ExactUser = $Exact<InexactUser>;3
4const user = {name: 'John Wilkes Booth'};5// These will both be satisfied because they are equivalent:6const a: ExactUser = user;7const b: {name: string} = user;
This is an utility type to avoid, as it's clearer and more concinse to start off with an exact object type and make it inexact using object type spread (if you wish to have both inexact and exact variants of one object type):
1type ExactUser = {name: string};2type InexactUser = {...ExactUser, ...};3
4const user = {name: 'John Wilkes Booth'};5const a: ExactUser = user;
$Diff<A, B>
As the name hints, $Diff<A, B>
is the type representing the set difference of A
and B
, i.e. A \ B
, where A
and B
are both object types. Here's an example:
1type Props = {name: string, age: number, ...};2type DefaultProps = {age: number};3type RequiredProps = $Diff<Props, DefaultProps>;4
5function setProps(props: RequiredProps) {6 // ...7}8
9setProps({name: 'foo'}); // Works10setProps({name: 'foo', age: 42, baz: false}); // Works, you can pass extra props too11setProps({age: 42}); // Error! `name` is required
11:10-11:18: Cannot call `setProps` with object literal bound to `props` because property `name` is missing in object literal [1] but exists in `Props` [2]. [prop-missing]
As you may have noticed, the example is not a random one.
$Diff
is exactly what the React definition file uses to define the type of the props accepted by a React Component.
Note that $Diff<A, B>
will error if the object you are removing properties from does not have the property being removed, i.e. if B
has a key that doesn't exist in A
:
1type Props = {name: string, age: number};2type DefaultProps = {age: number, other: string};3type RequiredProps = $Diff<Props, DefaultProps>; // Error! 4
5function setProps(props: RequiredProps) {6 props.name;7 // ...8}
3:28-3:32: Cannot instantiate `$Diff` because undefined property `other` [1] is incompatible with string [2]. [incompatible-type]
As a workaround, you can specify the property not present in A
as optional. For example:
1type A = $Diff<{}, {nope: number}>; // Error! 2type B = $Diff<{}, {nope: number | void}>; // Works3
4const a: A = {};5const b: B = {};
1:16-1:17: Cannot instantiate `$Diff` because undefined property `nope` [1] is incompatible with number [2]. [incompatible-type]
$Rest<A, B>
$Rest<A, B>
is the type that represents the runtime object rest operation, e.g.: const {foo, ...rest} = obj
, where A
and B
are both object types.
The resulting type from this operation will be an object type containing A
's own properties that are not own properties in B
.
In flow, we treat all properties on exact object types as own.
For inexact objects, a property may or may not be own.
For example:
1type Props = {name: string, age: number};2
3const props: Props = {name: 'Jon', age: 42};4const {age, ...otherProps} = props;5otherProps as $Rest<Props, {age: number}>;6otherProps.age; // Error!
6:12-6:14: Cannot get `otherProps.age` because property `age` is missing in rest of object pattern [1]. [prop-missing]
The main difference with $Diff<A, B>
, is that $Rest<A, B>
aims to represent the true runtime rest operation,
which implies that exact object types are treated differently in $Rest<A, B>
.
For example, $Rest<{n: number}, {...}>
will result in {n?: number}
because an in-exact empty object may have an n
property,
while $Diff<{n: number}, {...}>
will result in {n: number}
.
$NonMaybeType<T>
$NonMaybeType<T>
converts a type T
to a non-maybe type.
In other words, the values of $NonMaybeType<T>
are the values of T
except for null
and undefined
.
1type MaybeName = ?string;2type Name = $NonMaybeType<MaybeName>;3
4'Gabriel' as MaybeName; // Works5null as MaybeName; // Works6'Gabriel' as Name; // Works7null as Name; // Error! `null` can't be annotated as Name because Name is not a maybe type
7:1-7:4: Cannot cast `null` to `Name` because null [1] is incompatible with string [2]. [incompatible-cast]
$KeyMirror<O>
$KeyMirror<Obj>
is a special case of $ObjMapi<Obj, F>
, when F
is the identity
function type, ie. <K>(K) => K
. In other words, it maps each property of an object
to the type of the property key. Instead of writing $ObjMapi<Obj, <K>(K) => K>
,
you can write $KeyMirror<Obj>
. For example:
1const obj = {2 a: true,3 b: 'foo'4};5
6declare function run<O: {...}>(o: O): $KeyMirror<O>;7
8// newObj is of type {a: 'a', b: 'b'}9const newObj = run(obj);10
11newObj.a as 'a'; // Works12newObj.b as 'a'; // Error! String 'b' is incompatible with 'a'
12:1-12:8: Cannot cast `newObj.b` to string literal `a` because string literal `b` [1] is incompatible with string literal `a` [2]. [incompatible-cast]
Tip: Prefer using $KeyMirror
instead of $ObjMapi
(if possible) to fix certain
kinds of [invalid-exported-annotation]
errors.
Class<T>
Given a type T
representing instances of a class C
, the type Class<T>
is the type of the class C
.
For example:
1class Store {}2class ExtendedStore extends Store {}3class Model {}4
5function makeStore(storeClass: Class<Store>) {6 return new storeClass();7}8
9makeStore(Store) as Store;10makeStore(ExtendedStore) as Store;11makeStore(Model) as Model; // Error!
11:1-11:16: Cannot cast `makeStore(...)` to `Model` because `Store` [1] is incompatible with `Model` [2]. [incompatible-cast]11:11-11:15: Cannot call `makeStore` with `Model` bound to `storeClass` because `Model` [1] is incompatible with `Store` [2]. [incompatible-call]
For classes that take type parameters, you must also provide the parameter. For example:
1class ParamStore<T> {2 constructor(data: T) {}3}4
5function makeParamStore<T>(storeClass: Class<ParamStore<T>>, data: T): ParamStore<T> {6 return new storeClass(data);7}8makeParamStore(ParamStore, 1) as ParamStore<number>;9makeParamStore(ParamStore, 1) as ParamStore<boolean>; // Error!
9:28-9:28: Cannot call `makeParamStore` with `1` bound to `data` because number [1] is incompatible with boolean [2]. [incompatible-call]
$Exports<T>
The following are functionally equivalent
import typeof * as T from 'my-module';
type T = $Exports<'my-module'>;
The advantage of the $Exports
syntax is that you can export
the type on the same line
export type T = $Exports<'my-module'>;
where as you would otherwise need to export an alias in the import typeof
case
import typeof * as T from 'my-module';
export type MyModuleType = T;
StringPrefix
and StringSuffix
≥0.242
The StringPrefix
and StringSuffix
types represent strings with the specified prefix or suffix, respectively.
Their first type argument must be a string literal type, representing the prefix or suffix.
You could use StringPrefix
to define a type that accepts strings which start with data-
:
1type DataProp = StringPrefix<'data-'>;2'data-foo' as DataProp; // OK3'data-bar' as DataProp; // OK4'random string' as DataProp; // ERROR
4:1-4:15: Cannot cast `'random string'` to `DataProp` because string [1] is incompatible with string prefixed with `data-` [2]. [incompatible-cast]
You could use StringSuffix
to define a type that accepts strings which end with !
:
1type Exclaim = StringSuffix<'!'>;2'yay!' as Exclaim; // OK3'woo!' as Exclaim; // OK4'random string' as Exclaim; // ERROR
4:1-4:15: Cannot cast `'random string'` to `Exclaim` because string [1] is incompatible with string suffixed with `!` [2]. [incompatible-cast]
You can combine these with intersection types:
1type CSSVar = StringPrefix<'var(--'> & StringSuffix<')'>;2'var(--color)' as CSSVar; // OK3'random string' as CSSVar; // ERROR
3:1-3:15: Cannot cast `'random string'` to `CSSVar` because string [1] is incompatible with string prefixed with `var(--` [2]. [incompatible-cast]3:1-3:15: Cannot cast `'random string'` to `CSSVar` because string [1] is incompatible with string suffixed with `)` [2]. [incompatible-cast]
Both utilities accept an optional second type argument, which is the type of the remainder:
1type Price = StringPrefix<'$', '1' | '2'>;2'$1' as Price; // OK3'$2' as Price; // OK4'$999' as Price; // ERROR
4:1-4:6: Cannot cast `'$999'` to `Price` because string with prefix `$` removed [1] is incompatible with union type [2]. [incompatible-cast]
When not specified, the type of the remainder is just string
.
Deprecated utility types
$PropertyType<T, k>
WARNING: $PropertyType
is deprecated as of Flow version 0.155, and will be removed in a future version of Flow.
$PropertyType<T, 'k'>
is equivalent to the T['k']
indexed access type.
$ElementType<T, K>
WARNING: $ElementType
is deprecated as of Flow version 0.155, and will be removed in a future version of Flow.
$ElementType<T, K>
is equivalent to the T[K]
indexed access type.
To-be-removed utility types
$TupleMap<T, F>
$TupleMap<T, F>
takes an iterable type T
(e.g.: Tuple
or Array
), and a function type F
,
and returns the iterable type obtained by mapping the type of each value in the iterable with the provided function type F
.
This is analogous to the JavaScript function map
.
Following our example from $ObjMap<T>
, let's assume that run
takes an array of functions, instead of an object, and maps over them returning an array of the function call results. We could annotate its return type like this:
1// Function type that takes a `() => V` and returns a `V` (its return type)2type ExtractReturnType = <V>(() => V) => V3
4function run<A, I: Array<() => A>>(iter: I): $TupleMap<I, ExtractReturnType> { 5 return iter.map(fn => fn()); 6}7
8const arr = [() => 'foo', () => 'bar'];9run(arr)[0] as string; // Works10run(arr)[1] as string; // Works11run(arr)[1] as boolean; // Error!
4:46-4:54: Cannot resolve name `$TupleMap`. [cannot-resolve-name]5:19-5:20: An annotation on `fn` is required because Flow cannot infer its type from local context. [missing-local-annot]
Removed utility types
These utility types used to exist, but no longer exist in latest version of Flow.
$Call<F, T...>
≤0.247
NOTE: Please use Conditional Types or Indexed Access Types to extract types instead.
$Call<F, T...>
is a type that represents the result of calling the given function type F
with 0 or more arguments T...
.
This is analogous to calling a function at runtime (or more specifically, it's analogous to calling Function.prototype.call
), but at the type level; this means that function type calls happens statically, i.e. not at runtime.
Let's see a couple of examples:
1// Takes an object type, returns the type of its `prop` key2type ExtractPropType = <T>({prop: T, ...}) => T;3type Obj = {prop: number};4type PropType = $Call<ExtractPropType, Obj>; // Call `ExtractPropType` with `Obj` as an argument 5type Nope = $Call<ExtractPropType, {nope: number}>; // Error! Argument doesn't match `Obj`. 6
75 as PropType; // Works8true as PropType; // Error! PropType is a number
4:17-4:21: Cannot resolve name `$Call`. [cannot-resolve-name]5:13-5:17: Cannot resolve name `$Call`. [cannot-resolve-name]
1// Takes a function type, and returns its return type2type ExtractReturnType = <R>(() => R) => R;3type Fn = () => number;4type ReturnType = $Call<ExtractReturnType, Fn>; 5
65 as ReturnType; // Works7true as ReturnType; // Error! ReturnType is a number
4:19-4:23: Cannot resolve name `$Call`. [cannot-resolve-name]
$Call
can be very powerful because it allows you to make calls in type-land that you would otherwise have to do at runtime.
The type-land calls happen statically and will be erased at runtime.
1// Getting return types:2function getFirstValue<V>(map: Map<string, V>): ?V {3 for (const [key, value] of map.entries()) {4 return value;5 }6 return null;7}8
9// Using $Call, we can get the actual return type of the function above:10type Value = $Call<typeof getFirstValue, Map<string, number>>; 11
125 as Value;13true as Value; // Error! Value is a `number`14
15// We could generalize it further:16type GetMapValue<M> =17 $Call<typeof getFirstValue, M>; 18
195 as GetMapValue<Map<string, number>>;20true as GetMapValue<Map<string, boolean>>;21true as GetMapValue<Map<string, number>>; // Error! value is a `number`
10:14-10:18: Cannot resolve name `$Call`. [cannot-resolve-name]17:3-17:7: Cannot resolve name `$Call`. [cannot-resolve-name]
$ObjMap<T, F>
≤0.246
NOTE: Please use Mapped Types instead.
ObjMap<T, F>
takes an object type T
, and a function type F
, and returns the object type obtained by mapping the type of each value in the object with the provided function type F
. In other words, $ObjMap
will call (at the type level) the given function type F
for every property value type in T
, and return the resulting object type from those calls.
Let's see an example. Suppose you have a function called run
that takes an object of thunks (functions in the form () => A
) as input:
1function run<O: {[key: string]: (...$ReadOnlyArray<mixed>) => mixed}>(o: O): $FlowFixMe {2 return Object.keys(o).reduce<{[string]: (...$ReadOnlyArray<mixed>) => mixed}>(3 (acc, k) => ({...acc, [(k: string)]: o[k]()}),4 {},5 );6}
The function's purpose is to run all the thunks and return an object made of values. What's the return type of this function?
The keys are the same, but the values have a different type, namely the return type of each function. At a value level (the implementation of the function) we're essentially mapping over the object to produce new values for the keys. How to express this at a type level?
This is where ObjMap<T, F>
comes in handy
1// let's write a function type that takes a `() => V` and returns a `V` (its return type)2type ExtractReturnType = <V>(() => V) => V;3
4declare function run<O: {[key: string]: (...$ReadOnlyArray<mixed>) => mixed}>(o: O): $ObjMap<O, ExtractReturnType>; 5
6const o = {7 a: () => true,8 b: () => 'foo'9};10
11run(o).a as boolean; // Works12run(o).b as string; // Works13run(o).b as boolean; // Error! `b` is a string14run(o).c; // Error! `c` was not in the original object
4:86-4:92: Cannot resolve name `$ObjMap`. [cannot-resolve-name]
This is extremely useful for expressing the return type of functions that manipulate objects values.
You could use a similar approach (for instance) to provide the return type of bluebird's Promise.props
function,
which is like Promise.all
but takes an object as input.
Here's a possible declaration of this function, which is very similar to our first example:
1declare function props<A, O: {[key: string]: A}>(promises: O): Promise<$ObjMap<O, <T>(p: Promise<T> | T) => T>>>; 2
3const promises = {a: Promise.resolve(42)};4props(promises).then(o => {5 o.a as 42; // Works6 o.a as 43; // Error! Flow knows it's 427});
1:112-1:112: Unexpected token `>`, expected the token `;`
$ObjMapi<T, F>
≤0.246
NOTE: Please use Mapped Types instead.
ObjMapi<T, F>
is similar to ObjMap<T, F>
. The difference is that function
type F
will be called with both the key and value types of the elements of
the object type T
, instead of just the value types. For example:
1const o = {2 a: () => true,3 b: () => 'foo'4};5
6type ExtractReturnObjectType = <K, V>(K, () => V) => { k: K, v: V };7
8declare function run<O: {...}>(o: O): $ObjMapi<O, ExtractReturnObjectType>; 9
10run(o).a as {k: 'a', v: boolean}; // Works11run(o).b as {k: 'b', v: string}; // Works12run(o).a as {k: 'b', v: boolean}; // Error! `a.k` is "a"13run(o).b as {k: 'b', v: number}; // Error! `b.v` is a string14run(o).c; // Error! `c` was not in the original object
8:39-8:46: Cannot resolve name `$ObjMapi`. [cannot-resolve-name]
$ObjMapConst<O, T>
≤0.246
NOTE: Please use Mapped Types instead.
$ObjMapConst<Obj, T>
is a special case of $ObjMap<Obj, F>
, when F
is a constant
function type, e.g. () => T
. Instead of writing $ObjMap<Obj, () => T>
, you
can write $ObjMapConst<Obj, T>
. For example:
1const obj = {2 a: true,3 b: 'foo'4};5
6declare function run<O: {...}>(o: O): $ObjMapConst<O, number>; 7
8// newObj is of type {a: number, b: number}9const newObj = run(obj);10
11newObj.a as number; // Works12newObj.b as string; // Error! Property `b` is a number
6:39-6:50: Cannot resolve name `$ObjMapConst`. [cannot-resolve-name]
Tip: Prefer using $ObjMapConst
instead of $ObjMap
(if possible) to fix certain
kinds of [invalid-exported-annotation]
errors.
$Partial
≤0.202
A former alias of Partial. Support was removed in version 0.203.
$Shape<T>
≤0.206
NOTE: This utility is unsafe - please use Partial
documented above to make all of an object's fields optional.
A variable of type $Shape<T>
, where T
is some object type, can be assigned objects o
that contain a subset of the properties included in T
. For each property p: S
of T
,
the type of a potential binding of p
in o
must be compatible with S
.
For example
1type Person = {2 age: number,3 name: string,4};5// $FlowIgnore[deprecated-utility]6type PersonDetails = $Shape<Person>;7
8const person1: Person = {age: 28}; // ERROR: missing `name` 9const person2: Person = {name: 'a'}; // ERROR: missing `age` 10const person3: PersonDetails = {age: 28}; // OK11const person4: PersonDetails = {name: 'a'}; // OK12const person5: PersonDetails = {age: 28, name: 'a'}; // OK13const person6: PersonDetails = {age: '28'}; // ERROR: string is incompatible with number
8:25-8:33: Cannot assign object literal to `person1` because property `name` is missing in object literal [1] but exists in `Person` [2]. [prop-missing]9:25-9:35: Cannot assign object literal to `person2` because property `age` is missing in object literal [1] but exists in `Person` [2]. [prop-missing]
NOTE: $Shape<T>
is not equivalent to T
with all its fields marked as optional.
In particular, Flow unsoundly allows $Shape<T>
to be used as a T
in several
contexts. For example in
const personShape: PersonDetails = {age: 28};
personShape as Person;
Flow will unsoundly allow this last cast to succeed.
It is also not equivalent to itself in some contexts:
function f<T>(input: $Shape<T>): $Shape<T> {
return input; // ERROR: `T` is incompatible with `$Shape` of `T`
}
This utility type is deprecated and will be deleted in the future -
use Partial
instead.