不透明型エイリアス
不透明型エイリアスは、定義されたファイルの外では基礎となる型へのアクセスを許可しない型エイリアスです。
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;