跳至主要內容

不透明類型別名

不透明類型別名是不允許在定義它們的檔案外部存取其底層類型的類型別名。

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};

函式庫定義

你也可以在函式庫定義中宣告不透明類型別名。在那裡,你可以省略底層類型,但仍可以選擇性地包含父類型。

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