Skip to main content

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:

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].

Note that using $Values on the typeof an object 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 literal union [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 $ObjMap<T>, 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<$ObjMap<Obj, <T>(T) => Array<T>>> // 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 literal union [2]. [incompatible-cast]
4:1-4:1: Cannot cast `3` to `T` because number [1] is incompatible with literal union [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 `Pick` [1]. [prop-missing]
7:9-7:11: Cannot get `justBaz.bar` because property `bar` (did you mean `baz`?) is missing in `Pick` [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: Record = {}; // error
6// Indexers do not have this same requirement7const idx: IndexedObject = {}; // no error
5:12-5:17: Cannot use `Record` [1] without 2 type arguments. [missing-type-arg]

$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.

$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!
11:1-11:11: Cannot cast `run(...)[1]` to boolean because string [1] is incompatible with boolean [2]. [incompatible-cast]

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;

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.

$Partial 0.202

A former alias of Partial. Support was removed in version 0.203.

$Shape<T>

NOTE: Deprecated! 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.

$Call<F, T...>

NOTE: Deprecated! This utility is deprecated as of Flow version 0.208 - 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 argument5type Nope = $Call<ExtractPropType, {nope: number}>;  // Error! Argument doesn't match `Obj`.
6 75 as PropType; // Works8true as PropType; // Error! PropType is a number
5:36-5:49: Cannot instantiate `$Call` because property `prop` is missing in object type [1] but exists in object type [2] in the first argument. [prop-missing]
8:1-8:4: Cannot cast `true` to `PropType` because boolean [1] is incompatible with number [2]. [incompatible-cast]
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
7:1-7:4: Cannot cast `true` to `ReturnType` because boolean [1] is incompatible with number [2]. [incompatible-cast]

$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`
13:1-13:4: Cannot cast `true` to `Value` because boolean [1] is incompatible with number [2]. [incompatible-cast]
21:1-21:4: Cannot cast `true` to `GetMapValue` because boolean [1] is incompatible with number [2]. [incompatible-cast]

$ObjMap<T, F>

NOTE: Deprecated! This utility is deprecated as of Flow version 0.211- 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 string
14run(o).c; // Error! `c` was not in the original object
13:1-13:8: Cannot cast `run(...).b` to boolean because string [1] is incompatible with boolean [2]. [incompatible-cast]
14:8-14:8: Cannot get `run(...).c` because property `c` is missing in object type [1]. [prop-missing]

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, typeof $await>>;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 42
7});
6:3-6:5: Cannot cast `o.a` to number literal `43` because number [1] is incompatible with number literal `43` [2]. [incompatible-cast]

$ObjMapi<T, F>

NOTE: Deprecated! This utility is deprecated as of Flow version 0.211- 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 string
14run(o).c; // Error! `c` was not in the original object
12:1-12:8: Cannot cast `run(...).a` to object type because string literal `a` [1] is incompatible with string literal `b` [2] in property `k`. [incompatible-cast]
13:1-13:8: Cannot cast `run(...).b` to object type because string [1] is incompatible with number [2] in property `v`. [incompatible-cast]
14:8-14:8: Cannot get `run(...).c` because property `c` is missing in object type [1]. [prop-missing]

$ObjMapConst<O, T>

NOTE: Deprecated! This utility is deprecated as of Flow version 0.211- 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
12:1-12:8: Cannot cast `newObj.b` to string because number [1] is incompatible with string [2]. [incompatible-cast]

Tip: Prefer using $ObjMapConst instead of $ObjMap (if possible) to fix certain kinds of [invalid-exported-annotation] errors.