Opaque Type Aliases
Opaque type aliases are type aliases that do not allow access to their underlying type outside of the file in which they are defined.
opaque type ID = string;
Opaque type aliases, like regular type aliases, may be used anywhere a type can be used.
// @flow opaque type ID = string; function identity(x: ID): ID { return x; } export type {ID};
Opaque Type Alias Syntax
Opaque type aliases are created using the words opaque type
followed by its name, an equals sign =
, and a type definition.
opaque type Alias = Type;
You can optionally add a subtyping constraint to an opaque type alias by adding a colon :
and a type after the name.
opaque type Alias: SuperType = Type;
Any type can appear as the super type or type of an opaque type alias.
opaque type StringAlias = string; opaque type ObjectAlias = { property: string, method(): number, }; opaque type UnionAlias = 1 | 2 | 3; opaque type AliasAlias: ObjectAlias = ObjectAlias; opaque type VeryOpaque: AliasAlias = ObjectAlias;
Opaque Type Alias Type Checking
Within the Defining File
When in the same file the alias is defined, opaque type aliases behave exactly as regular type aliases do.
//@flow opaque type NumberAlias = number; (0: NumberAlias); function add(x: NumberAlias, y: NumberAlias): NumberAlias { return x + y; } function toNumberAlias(x: number): NumberAlias { return x; } function toNumber(x: NumberAlias): number { return x; }
Outside the Defining File
When importing an opaque type alias, it behaves like a nominal type, hiding its underlying type.
exports.js
export opaque type NumberAlias = number;
imports.js
import type {NumberAlias} from './exports'; (0: NumberAlias) // Error: 0 is not a NumberAlias! function convert(x: NumberAlias): number { return x; // Error: x is not a number! }
Subtyping Constraints
When you add a subtyping constraint to an opaque type alias, we allow the opaque type to be used as the super type when outside of the defining file.
exports.js
export opaque type ID: string = string;
imports.js
import type {ID} from './exports'; function formatID(x: ID): string { return "ID: " + x; // Ok! IDs are strings. } function toID(x: string): ID { return x; // Error: strings are not IDs. }
When you create an opaque type alias with a subtyping constraint, the type in the type position must be a subtype of the type in the super type position.
//@flow opaque type Bad: string = number; // Error: number is not a subtype of string opaque type Good: {x: string} = {x: string, y: number};
Generics
Opaque type aliases can also have their own generics, and they work exactly as generics do in regular type aliases
// @flow opaque type MyObject<A, B, C>: { foo: A, bar: B } = { foo: A, bar: B, baz: C, }; var val: MyObject<number, boolean, string> = { foo: 1, bar: true, baz: 'three', };
Library Definitions
You can also declare opaque type aliases in libdefs. There, you omit the underlying type, but may still optionally include a super type.
declare opaque type Foo; declare opaque type PositiveNumber: number;
© 2013–present Facebook Inc.
Licensed under the MIT License.
https://flow.org/en/docs/types/opaque-types