跳至主要内容

不透明类型别名

不透明类型别名是不允许在定义它们的外部访问其底层类型的类型别名。

1opaque type ID = string;

不透明类型别名与普通类型别名一样,可以在任何可以使用类型的场合使用。

1opaque type ID = string;2
3function identity(x: ID): ID {4  return x;5}6export type {ID};

不透明类型别名语法

不透明类型别名使用关键字 opaque type 后跟其名称、等号 = 和类型定义来创建。

opaque type Alias = Type;

您可以选择通过在名称后添加冒号 : 和类型来为不透明类型别名添加子类型约束。

opaque type Alias: SuperType = Type;

任何类型都可以作为不透明类型别名的超类型或类型。

1opaque type StringAlias = string;2opaque type ObjectAlias = {3  property: string,4  method(): number,5};6opaque type UnionAlias = 1 | 2 | 3;7opaque type AliasAlias: ObjectAlias = ObjectAlias;8opaque type VeryOpaque: AliasAlias = ObjectAlias;

不透明类型别名类型检查

在定义文件中

在定义别名的同一个文件中,不透明类型别名的行为与普通 类型别名 完全相同。

1opaque type NumberAlias = number;2
30 as NumberAlias;4
5function add(x: NumberAlias, y: NumberAlias): NumberAlias {6    return x + y;7}8function toNumberAlias(x: number): NumberAlias { return x; }9function toNumber(x: NumberAlias): number { return x; }

在定义文件之外

导入不透明类型别名时,它的行为类似于 名义类型,隐藏其底层类型。

exports.js

export opaque type NumberAlias = number;

imports.js

import type {NumberAlias} from './exports';

0 as NumberAlias; // Error: 0 is not a NumberAlias!

function convert(x: NumberAlias): number {
return x; // Error: x is not a number!
}

子类型约束

当您为不透明类型别名添加子类型约束时,我们允许在定义文件之外使用不透明类型作为超类型。

exports.js

1export 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.
}

当您创建具有子类型约束的不透明类型别名时,类型位置中的类型必须是超类型位置中的类型的子类型。

1opaque type Bad: string = number; // Error: number is not a subtype of string
2opaque type Good: {x: string, ...} = {x: string, y: number};
1:27-1:32: number [1] is incompatible with string [2]. [incompatible-type]

泛型

不透明类型别名也可以拥有自己的 泛型,它们的工作方式与普通 类型别名 中的泛型完全相同。

1opaque type MyObject<A, B, C>: {foo: A, bar: B, ...} = {2  foo: A,3  bar: B,4  baz: C,5};6
7var val: MyObject<number, boolean, string> = {8  foo: 1,9  bar: true,10  baz: 'three',11};

库定义

您也可以在 libdefs 中声明不透明类型别名。在那里,您省略底层类型,但仍然可以选择包含超类型。

1declare opaque type Foo;2declare opaque type PositiveNumber: number;