Thanks to visit codestin.com
Credit goes to flow.org

Skip to main content

Utility Types

Flow provides a set of utility types to operate on other types to create new types.

keyof 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 = keyof typeof countries;8
9const italy: Country = 'IT'; // Works10const nope: Country = 'nope'; // Error!prop-missingCannot assign 'nope' to nope because property nope is missing in object literal [1].

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:

1type Props = {2  name: string,3  age: number,4};5
6// The following two types are equivalent:7type PropValues = string | number;8type PropValues2 = Values<Props>;9
10const name: PropValues2 = 'Jon';  // Works11const age: PropValues2 = 42;  // Works12const fn: PropValues2 = true; // Error!incompatible-typeCannot assign true to fn because: Either boolean [1] is incompatible with number [2]. Or boolean [1] is incompatible with string [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`.incompatible-typeCannot call acceptsValues with 3 bound to x because number [1] is incompatible with Values [2].

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. 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!cannot-writeCannot assign 42 to props.age because property age is not writable.11}

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>

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

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: `PartialPerson` is not a `Person`incompatible-typeCannot 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].

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!incompatible-typeCannot 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].13
14function okPerson(o: Readonly<Partial<Person>>) {15  // Can't mutate - it's read-only!16}17okPerson(person); // Works

Required<T>

The Required utility type is the opposite of Partial: it converts all of an object or interface’s optional fields to be required.

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` propertyincompatible-typeCannot assign object literal to b because property name is missing in object literal [1] but exists in PartialPerson [2].

For tuples:

1type AllOptional = [a?: number, b?: string];2[] as Required<AllOptional>; // ERROR: like `[a: number, b: string]` nowinvalid-tuple-arityCannot cast array literal to required of AllOptional because empty array literal [1] has 0 elements but AllOptional [2] has 2 elements.

ReturnType<F>

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 booleanincompatible-typeCannot cast 1 to Bool because number [1] is incompatible with boolean [2].

Parameters<F>

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 elementsinvalid-tuple-indexCannot access number literal 2 on Tuple because tuple type [1] only has 2 elements, so index 2 is out of bounds.

Exclude<T, U>

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; // errorincompatible-typeCannot cast 1 to T because number [1] is incompatible with Exclude [2].32 as T; // ok43 as T; // errorincompatible-typeCannot cast 3 to T because number [1] is incompatible with Exclude [2].54 as T; // ok

Extract<T, U>

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; // errorincompatible-typeCannot cast new Car() to T because: Either Car [1] is incompatible with Dog [2]. Or Car [1] is incompatible with Cat [3].7new Dog() as T; // ok8new Cat() as T; // ok

ThisParameterType<F>

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; // errorincompatible-typeCannot cast '1' to T because string [1] is incompatible with number [2].32 as T; // ok

OmitThisParameter<F>

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 numberincompatible-typeCannot call hasThisParam because global object [1] is incompatible with number [2].7noThisParam(''); // ok: no this type requirement

Awaited<T>

Awaited<T> unwraps a Promise type to extract the type of its resolved value. If T is not a Promise, it returns T unchanged.

1type Response = Awaited<Promise<string>>; // Evaluates to string2'hello' as Response; // OK342 as Response; // Error: number is not stringincompatible-typeCannot cast 42 to Response because number [1] is incompatible with string [2].

This is useful when you need to refer to the resolved type of a Promise without manually unwrapping it. If T is not a Promise, Awaited<T> simply evaluates to T:

1type A = Awaited<Promise<number>>; // number2type B = Awaited<string>; // string (non-Promise types are returned as-is)3
442 as A; // OK5'hello' as B; // OK6'hello' as A; // Error: string is not numberincompatible-typeCannot cast 'hello' to A because string [1] is incompatible with number [2].742 as B; // Error: number is not stringincompatible-typeCannot cast 42 to B because number [1] is incompatible with string [2].

You can combine Awaited with other utility types like ReturnType to extract the resolved type from an async function's return type:

1async function fetchUser(): Promise<{name: string}> {2  return {name: 'George'};3}4
5type User = Awaited<ReturnType<typeof fetchUser>>;6
7const user: User = {name: 'George'}; // OK8const bad: User = 'not a user'; // Errorincompatible-typeCannot assign 'not a user' to bad because string [1] is incompatible with object type [2].

Pick<O, Keys>

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 missingprop-missingCannot get fooAndBar.baz because property baz (did you mean bar?) is missing in Pick [1].6fooAndBar.foo as number; // ok7fooAndBar.bar as string; // ok

Omit<O, Keys>

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 fooprop-missingCannot get justBaz.foo because property foo is missing in Omit [1].7justBaz.bar; // error: missing barprop-missingCannot get justBaz.bar because property bar (did you mean baz?) is missing in Omit [1].

Record<Keys, Type>

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; // errorprop-missingCannot get numberRecord.baz because property baz (did you mean bar?) is missing in Record [1].

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 = {}; // errorincompatible-typeCannot assign object literal to rec because properties bar and foo are missing in object literal [1] but exist in Record [2].6// Indexers do not have this same requirement7const idx: IndexedObject = {}; // no error

NonNullable<T>

NonNullable<T> converts a type T to a non-maybe type. In other words, the values of NonNullable<T> are the values of T except for null and undefined.

1type MaybeName = ?string;2type Name = NonNullable<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 typeincompatible-typeCannot cast null to Name because null [1] is incompatible with string [2].

NoInfer<T>

NoInfer<T> prevents a type parameter from being inferred from the wrapped position. When Flow infers a type parameter T, it normally considers every position where T appears. Wrapping a position in NoInfer excludes it from inference, so T is determined only by the remaining (unwrapped) positions. The resulting type is still TNoInfer only affects inference, not the type itself.

This is useful when a generic function has multiple parameters that share a type parameter, but you want only some of them to drive inference. Without NoInfer, Flow may widen the type parameter to accommodate all arguments, allowing mismatches to go undetected.

Consider a function where both parameters use the same type parameter T:

1declare function assertEqual<T>(actual: T, expected: T): void;2
3assertEqual('hello', 42); // No error: T is inferred as string | number

Because both arguments contribute to inference, Flow widens T to string | number, and the call succeeds even though the two arguments have different types.

By wrapping the expected parameter with NoInfer, you can ensure T is inferred only from actual:

1declare function assertEqual<T>(actual: T, expected: NoInfer<T>): void;2
3assertEqual('hello', 'world'); // OK4assertEqual('hello', 42); // Error!incompatible-typeCannot call assertEqual with 42 bound to expected because number [1] is incompatible with string [2].

Now T is inferred as string from the first argument alone, and 42 fails to match.

Nested types

NoInfer also works when T appears inside a more complex type. Any occurrence of the type parameter within NoInfer is excluded from inference:

1declare function createSignal<T>(2  initialValue: T,3  defaultValue: NoInfer<T>,4): void;5
6createSignal('hello', 'default'); // OK7createSignal('hello', 42); // Error!incompatible-typeCannot call createSignal with 42 bound to defaultValue because number [1] is incompatible with string [2].

Callbacks

You can use NoInfer in callback parameter positions to prevent the callback from influencing the type parameter while still receiving the inferred type:

1declare function filter<T>(2  items: Array<T>,3  predicate: (item: NoInfer<T>) => boolean,4): Array<T>;5
6const numbers: Array<number> = [1, 2, 3];7filter(numbers, (item) => item > 1); // OK

Here T is inferred as number from the items argument. The predicate callback receives item typed as number but does not participate in inferring T.

$KeyMirror<O>

$KeyMirror<Obj> maps each property of an object to the type of the property key. For example:

1const obj = {2  a: true,3  b: 'foo'4};5
6declare function run<O extends {...}>(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'incompatible-typeCannot cast newObj.b to string literal a because string literal b [1] is incompatible with string literal a [2].

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!incompatible-typeCannot cast makeStore(...) to Model because Store [1] is incompatible with Model [2].incompatible-typeCannot call makeStore with Model bound to storeClass because Model [1] is incompatible with Store [2].

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!incompatible-typeCannot call makeParamStore with 1 bound to data because number [1] is incompatible with boolean [2].

$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

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; // ERRORincompatible-typeCannot cast 'random string' to DataProp because string [1] is incompatible with string prefixed with data- [2].

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; // ERRORincompatible-typeCannot cast 'random string' to Exclaim because string [1] is incompatible with string suffixed with ! [2].

You can combine these with intersection types:

1type CSSVar = StringPrefix<'var(--'> & StringSuffix<')'>;2'var(--color)' as CSSVar; // OK3'random string' as CSSVar; // ERRORincompatible-typeCannot cast 'random string' to CSSVar because string [1] is incompatible with string prefixed with var(-- [2].incompatible-typeCannot cast 'random string' to CSSVar because string [1] is incompatible with string suffixed with ) [2].

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; // ERRORincompatible-typeCannot cast '$999' to Price because string with prefix $ removed [1] is incompatible with union type [2].

When not specified, the type of the remainder is just string.

$Exact<T> (Discouraged)

warning

Avoid $Exact<T>. Start with an exact object type and derive inexact variants from it using object type spread.

$Exact makes 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;

Prefer the inverse: define the exact type and spread it into the inexact one.

1type ExactUser = {name: string};2type InexactUser = {...ExactUser, ...};3
4const user = {name: 'John Wilkes Booth'};5const a: ExactUser = user;

See Also

  • Mapped Types — a general mechanism for transforming object types (generalizes many utility types)
  • Conditional Types — type-level conditionals for more complex transformations
  • Generics — most utility types are generic; understanding generics helps use them effectively
  • Indexed Access Types — extracting property types from objects and tuples