Spec-Zone.ru › Flow

Utility Types

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

TypeScript comparison

Most utility types align directly with TypeScript: Readonly, Pick, Omit, Record, Partial, Required, Exclude, Extract, NonNullable, Parameters, ReturnType, ConstructorParameters, InstanceType, Awaited, ThisParameterType, OmitThisParameter, NoInfer, Uppercase, Lowercase, Capitalize, Uncapitalize, and keyof. See Concepts that transfer cleanly from TypeScript for more.

keyof T​

You can extract the type of the keys from an object type. Typically this will be a union of string literal types:

const countries = {
  US: "United States",
  IT: "Italy",
  FR: "France"
};


type Country = keyof typeof countries;


const italy: Country = 'IT'; // Works
const nope: Country = 'nope'; // Error!

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 properties in an object type, or the elements of an array or tuple type:

type Props = {
  name: string,
  age: number,
};


// The following two types are equivalent:
type PropValues = string | number;
type PropValues2 = Values<Props>;


const name: PropValues2 = 'Jon';  // Works
const age: PropValues2 = 42;  // Works
const fn: PropValues2 = true; // Error!

For arrays and tuples:

type Arr = Array<string>;
type Str = Values<Arr>; //=> string
's' as Str; // OK


type Tup = [1, 2];
type Num = Values<Tup>; //=> 1 | 2
1 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:

const obj = {
  foo: 1,
  bar: 2,
};


function acceptsValues(x: Values<typeof obj>) { /* ... */ }


acceptsValues(1); // Works
acceptsValues(3); // Works, because the type was interpreted as `number`.

This behavior changes if you use Object.freeze on the object literal expression:

const obj = Object.freeze({
  foo: 1,
  bar: 2,
});


function acceptsValues(x: Values<typeof obj>) { /* ... */ }


acceptsValues(1); // Works
acceptsValues(3); // Error! Because the type was interpreted as `1 | 2`.

If you want to create an enum type, Flow Enums might be a better fit for your use-case.

TypeScript comparison

TypeScript has no Values<T> utility; the equivalent is the indexed access T[keyof T].

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:

type ReadOnlyObj = {
  readonly key: number,  // read-only field, marked by the `readonly` keyword
};
type ReadOnlyTuple = [readonly foo: number];

→

type ReadOnlyObj = Readonly<{
  key: number,
}>;
type 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:

type Props = {
  name: string,
  age: number,
};


type ReadOnlyProps = Readonly<Props>;


function render(props: ReadOnlyProps) {
  const {name, age} = props;  // Works
  props.age = 42;             // Error!
}

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:

type Obj = {
  readonly key: number,
};


type 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:

type Person = {
  name: string,
  age: number,
};
type PartialPerson = Partial<Person>;
// Above equivalent to `{name?: string, age?: number}`


const a: PartialPerson = {}; // OK
const b: PartialPerson = {name: 'George'}; // OK
const c: PartialPerson = {name: 'George', age: 123}; // OK


c as Person; // ERROR: `PartialPerson` is not a `Person`

For tuples:

type AllRequired = [number, string];
[] as Partial<AllRequired>; // OK: like `[a?: number, b?: string]` now

An 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:

type Person = {
  name: string,
  age: number,
};


const person: Person = {name: 'George', age: 123};


function noPerson(o: Partial<Person>) {
  // Can mutate:
  o.name = undefined;
}
noPerson(person); // Error!


function okPerson(o: Readonly<Partial<Person>>) {
  // Can't mutate - it's read-only!
}
okPerson(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:

type PartialPerson = {
  name?: string,
  age?: number,
};
type Person = Required<PartialPerson>;
// Above equivalent to `{name: string, age: number}`


const a: Person = {name: 'George', age: 123}; // OK
const b: Person = {age: 123}; // ERROR: missing `name` property

For tuples:

type AllOptional = [a?: number, b?: string];
[] as Required<AllOptional>; // ERROR: like `[a: number, b: string]` now

Pick<O, Keys>​

This utility type allows you to generate an object type using a subset of the fields from another object type.

type O = {foo: number, bar: string, baz: boolean};
type FooAndBar = Pick<O, 'foo' | 'bar'>;


declare const fooAndBar: FooAndBar;
fooAndBar.baz; // error: baz is missing
fooAndBar.foo as number; // ok
fooAndBar.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.

type O = {foo: number, bar: string, baz: boolean};
type JustBaz= Omit<O, 'foo' | 'bar'>;


declare const justBaz: JustBaz;
justBaz.baz as boolean; // ok
justBaz.foo; // error: missing foo
justBaz.bar; // error: missing bar

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.

type NumberRecord = Record<'foo' | 'bar', number>;
declare const numberRecord: NumberRecord;
numberRecord.foo as number; // ok
numberRecord.bar as number; // ok
numberRecord.baz; // error

Note that Record is different than using an indexer:

type NumberRecord = Record<'foo' | 'bar', number>;
type IndexedObject = {['foo' | 'bar']: number};


// Record uses explicit fields, which means they are all required
const rec: NumberRecord = {}; // error
// Indexers do not have this same requirement
const idx: IndexedObject = {}; // no error

Exclude<T, U>​

This utility type excludes all subtypes of U from T.

type T = Exclude<1 | 2 | 3 | 4, 1 | 3>; // evaluates to 2 | 4
1 as T; // error
2 as T; // ok
3 as T; // error
4 as T; // ok

Extract<T, U>​

This utility type retains only subtypes of U from T.

declare class Car {}
declare class Animal {}
declare class Dog extends Animal {}
declare class Cat extends Animal {}
type T = Extract<Car | Dog | Cat, Animal>; // evaluates to Dog | Cat
new Car() as T; // error
new Dog() as T; // ok
new Cat() as T; // ok

ReturnType<F>​

This utility type extracts the return type from a given function type.

declare function f(s: string, n: number): boolean;
type Bool = ReturnType<typeof f>;
true as Bool;
1 as Bool; // Error: number is not boolean

Parameters<F>​

This utility type extracts the parameter types from a given function type into a tuple type.

declare function f(s: string, n: number): boolean;
type Tuple = Parameters<typeof f>; // Evaluates to [string, number]
's' as Tuple[0];
1 as Tuple[1];
false as Tuple[2]; // Error: tuple type only has two elements

ConstructorParameters<C> ≥0.317​

This utility type extracts the parameter types of a class's constructor into a tuple type. Pass the class itself via typeof:

class Point {
  x: number;
  y: number;
  constructor(x: number, y: number) {
    this.x = x;
    this.y = y;
  }
}


type PointArgs = ConstructorParameters<typeof Point>; // Evaluates to [number, number]
[1, 2] as PointArgs; // OK
'x' as PointArgs[0]; // Error: string is not number

A class with no explicit constructor uses its synthesized default constructor, which takes no arguments:

class Empty {}
type EmptyArgs = ConstructorParameters<typeof Empty>; // Evaluates to []
[] as EmptyArgs; // OK
[1] as EmptyArgs; // Error: default constructor takes no arguments

A class without its own constructor inherits the parameters of its parent's constructor:

class Animal {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
}
class Dog extends Animal {} // no explicit constructor


type DogArgs = ConstructorParameters<typeof Dog>; // Inherited [string]
['Rex'] as DogArgs; // OK
[1] as DogArgs; // Error: number is not string

InstanceType<C> ≥0.317​

This utility type extracts the instance type produced by a class's constructor. Pass the class itself via typeof:

class User {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
}


type UserInstance = InstanceType<typeof User>; // Evaluates to User
declare const u: UserInstance;
u.name as string; // OK
u as User; // OK

This is useful when you have the type of a class (the static side, e.g. from a generic bound or a Class<T>) and need the type of the values it constructs.

For a generic class with no inference context, the class's type parameters resolve to their bounds (defaulting to unknown):

class Box<T> {
  value: T;
  constructor(value: T) {
    this.value = value;
  }
}


type BoxInstance = InstanceType<typeof Box>; // Box<unknown>
declare const b: BoxInstance;
b.value as unknown; // OK

ThisParameterType<F>​

This utility type extracts the type of the this parameter of a given function type.

type T = ThisParameterType<(this: number, bar: string) => void>; // Evaluates to number
'1' as T; // error
2 as T; // ok

OmitThisParameter<F>​

This utility type removes the this parameter from a given function type.

type HasThisParamFun = (this: number, bar: string) => void;
type NoThisParamFun = OmitThisParameter<HasThisParamFun> // Evaluates to (bar: string) => void
declare const hasThisParam: HasThisParamFun;
declare const noThisParam: NoThisParamFun;


hasThisParam(''); // error: global object is not number
noThisParam(''); // 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.

type Response = Awaited<Promise<string>>; // Evaluates to string
'hello' as Response; // OK
42 as Response; // Error: number is not string

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:

type A = Awaited<Promise<number>>; // number
type B = Awaited<string>; // string (non-Promise types are returned as-is)


42 as A; // OK
'hello' as B; // OK
'hello' as A; // Error: string is not number
42 as B; // Error: number is not string

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

async function fetchUser(): Promise<{name: string}> {
  return {name: 'George'};
}


type User = Awaited<ReturnType<typeof fetchUser>>;


const user: User = {name: 'George'}; // OK
const bad: User = 'not a user'; // 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.

type MaybeName = ?string;
type Name = NonNullable<MaybeName>;


'Gabriel' as MaybeName; // Works
null as MaybeName; // Works
'Gabriel' as Name; // Works
null as Name; // Error! `null` can't be annotated as Name because Name is not a maybe type

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 T — NoInfer 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:

declare function assertEqual<T>(actual: T, expected: T): void;


assertEqual('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:

declare function assertEqual<T>(actual: T, expected: NoInfer<T>): void;


assertEqual('hello', 'world'); // OK
assertEqual('hello', 42); // Error!

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:

declare function createSignal<T>(
  initialValue: T,
  defaultValue: NoInfer<T>,
): void;


createSignal('hello', 'default'); // OK
createSignal('hello', 42); // Error!

Callbacks

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

declare function filter<T>(
  items: Array<T>,
  predicate: (item: NoInfer<T>) => boolean,
): Array<T>;


const numbers: Array<number> = [1, 2, 3];
filter(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:

const obj = {
  a: true,
  b: 'foo'
};


declare function run<O extends {...}>(o: O): $KeyMirror<O>;


// newObj is of type {a: 'a', b: 'b'}
const newObj = run(obj);


newObj.a as 'a'; // Works
newObj.b as 'a'; // Error! String 'b' is incompatible with 'a'

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:

class Store {}
class ExtendedStore extends Store {}
class Model {}


function makeStore(storeClass: Class<Store>) {
  return new storeClass();
}


makeStore(Store) as Store;
makeStore(ExtendedStore) as Store;
makeStore(Model) as Model; // Error!

For classes that take type parameters, you must also provide the parameter. For example:

class ParamStore<T> {
  constructor(data: T) {}
}


function makeParamStore<T>(storeClass: Class<ParamStore<T>>, data: T): ParamStore<T> {
  return new storeClass(data);
}
makeParamStore(ParamStore, 1) as ParamStore<number>;
makeParamStore(ParamStore, 1) as ParamStore<boolean>; // Error!
TypeScript comparison

TypeScript has no native equivalent of Class<T>; the usual encodings are new (...args: any[]) => T, or typeof C for a specific class.

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

type DataProp = StringPrefix<'data-'>;
'data-foo' as DataProp; // OK
'data-bar' as DataProp; // OK
'random string' as DataProp; // ERROR

You could use StringSuffix to define a type that accepts strings which end with !:

type Exclaim = StringSuffix<'!'>;
'yay!' as Exclaim; // OK
'woo!' as Exclaim; // OK
'random string' as Exclaim; // ERROR

You can combine these with intersection types:

type CSSVar = StringPrefix<'var(--'> & StringSuffix<')'>;
'var(--color)' as CSSVar; // OK
'random string' as CSSVar; // ERROR

Both utilities accept an optional second type argument, which is the type of the remainder:

type Price = StringPrefix<'$', '1' | '2'>;
'$1' as Price; // OK
'$2' as Price; // OK
'$999' as Price; // ERROR

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

Uppercase<T>, Lowercase<T>, Capitalize<T>, Uncapitalize<T> ≥0.316​

These four utility types transform the casing of a string type:

  • Uppercase<T> converts every character to upper case.
  • Lowercase<T> converts every character to lower case.
  • Capitalize<T> converts the first character to upper case, leaving the rest unchanged.
  • Uncapitalize<T> converts the first character to lower case, leaving the rest unchanged.

The argument must be a string type. Applied to a string literal type, the result is the transformed literal:

type Greeting = Uppercase<'hello'>; // 'HELLO'
'HELLO' as Greeting; // OK
'hello' as Greeting; // ERROR
type Tag = Lowercase<'WARNING'>; // 'warning'
'warning' as Tag; // OK
'WARNING' as Tag; // ERROR

Capitalize and Uncapitalize only change the first character:

type Name = Capitalize<'flow'>; // 'Flow'
'Flow' as Name; // OK
'flow' as Name; // ERROR
'FLOW' as Name; // ERROR
type Field = Uncapitalize<'FullName'>; // 'fullName'
'fullName' as Field; // OK
'FullName' as Field; // ERROR
'fullname' as Field; // ERROR (the tail is left untouched)

They distribute over union types, transforming each member independently:

type Direction = Uppercase<'north' | 'south'>; // 'NORTH' | 'SOUTH'
'NORTH' as Direction; // OK
'SOUTH' as Direction; // OK
'south' as Direction; // ERROR

You can nest them to compose transformations:

type RoundTrip = Uncapitalize<Capitalize<'foo'>>;
'foo' as RoundTrip; // OK


type Nested = Uppercase<Lowercase<'AbC'>>;
'ABC' as Nested; // OK

Applied to the general string type, the result is still a string, but it represents only the strings that are already in the transformed form. A concrete literal must already be in that form to be a member:

type Loud = Uppercase<string>;
declare const x: Loud;
x as string; // OK
'ANYTHING' as Loud; // OK
'anything' as Loud; // ERROR (not already upper case)

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

type InexactUser = {name: string, ...};
type ExactUser = $Exact<InexactUser>;


const user = {name: 'John Wilkes Booth'};
// These will both be satisfied because they are equivalent:
const a: ExactUser = user;
const b: {name: string} = user;

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

type ExactUser = {name: string};
type InexactUser = {...ExactUser, ...};


const user = {name: 'John Wilkes Booth'};
const 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
  • Modernizing Legacy Flow Syntax — migrating legacy $-prefixed utilities such as $ObjMap, $PropertyType, and $NonMaybeType to their modern equivalents

© 2013–present Facebook Inc.
Licensed under the MIT License.
https://flow.org/en/docs/types/utilities

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API