メインコンテンツにスキップ

幅サブタイピング

オブジェクトが特定のセットのプロパティで注釈が付けられている位置で、オブジェクトの種類が不正確型の場合、そのオブジェクトに「追加」のプロパティがあっても安全に使用できます。

1function func(obj: {foo: string, ...}) {2  // ...3}4
5func({6  foo: "test", // Works!7  bar: 42      // Works!8});

func 内では、obj は少なくとも foo プロパティを持ち、プロパティのアクセス式 obj.foostring 型を持つことがわかります。

これは一般的に、「幅サブタイピング」と呼ばれる一種のサブタイピングです。この場合、より「幅広い」型 (つまり、より多くのプロパティを持つ型) が、より狭い型のサブタイプになります。

したがって、以下の例では、obj2obj1サブタイプになります。

1let obj1: {foo: string, ...}  = {foo: 'test'};2let obj2 = {foo: 'test', bar: 42};3obj2 as {foo: string, ...};

ただし、プロパティが確実に存在しないことを認識することは、しばしば役立ちます。

1function func(obj: {foo: string, ...} | {bar: number, ...}) {2  if (obj.foo) {3    obj.foo as string; // Error!
4 }5}
3:5-3:11: Cannot cast `obj.foo` to string because property `foo` of unknown type [1] is incompatible with string [2]. [incompatible-cast]

上のコードには型エラーがあります。Flow は呼び出し式 func({foo: 1, bar: 2}) も許可するためです。{foo: number, bar: number}{bar: number, ...} のサブタイプであり、パラメーターの共用型のメンバーの 1 つです。

プロパティの非存在を主張することが役立つこのような場合、完全なオブジェクト型 を使用できます。

1function func(obj: {foo: string} | {bar: number}) {2  if (obj.foo) {3    obj.foo as string; // Works!4  }5}

完全なオブジェクト型 は幅サブタイピングを無効化し、追加のプロパティが存在しないようにします。

正確なオブジェクトタイプを使用すると、実行時に追加のプロパティがなくなることが Flow に認識されるため、リファインメント をさらに具体的にすることができます。