インデックスアクセス型
Flowのインデックスアクセス型を使用すると、オブジェクト、配列、またはタプル型のプロパティの型を取得できます。
使用方法
オブジェクト型のプロパティへのアクセス
1type Cat = {2 name: string,3 age: number,4 hungry: boolean,5};6
7type Hungry = Cat['hungry']; // type Hungry = boolean8const isHungry: Hungry = true; // OK - `Hungry` is an alias for `boolean`9
10// The index can be a type, not just a literal:11type AgeProp = 'age';12type Age = Cat[AgeProp]; // type Age = number13const catAge: Age = 6; // OK - `Age` is an alias for `number`
配列型の要素へのアクセス(配列のインデックス(数値)から型を取得)
1type CatNames = Array<string>;2
3type CatName = CatNames[number]; // type CatName = string4const myCatsName: CatName = 'whiskers'; // OK - `CatName` is an alias for `string`
タプル型の要素へのアクセス
1type Pair = [string, number];2
3const name: Pair[0] = 'whiskers'; // OK - `Pair[0]` is an alias for `string`4const age: Pair[1] = 6; // OK - `Pair[1]` is an alias for `number`5const wrong: Pair[2] = true; // Error - `Pair` only has two elements
5:19-5:19: Cannot access number literal `2` on `Pair` because `Pair` [1] only has 2 elements, so index 2 is out of bounds. [invalid-tuple-index]
インデックスはユニオン型にすることができ、$Keys<...>
の呼び出し結果を含めることができます。
1type Cat = {2 name: string,3 age: number,4 hungry: boolean,5};6
7type Values = Cat[$Keys<Cat>]; // type Values = string | number | boolean
インデックスはジェネリクスにすることもできます。
1function getProp<O: {+[string]: mixed}, K: $Keys<O>>(o: O, k: K): O[K] {2 return o[k];3}4
5const x: number = getProp({a: 42}, 'a'); // OK6const y: string = getProp({a: 42}, 'a'); // Error - `number` is not a `string` 7getProp({a: 42}, 'b'); // Error - `b` does not exist in object type
6:19-6:39: Cannot assign `getProp(...)` to `y` because number [1] is incompatible with string [2]. [incompatible-type]7:18-7:20: Cannot call `getProp` because property `b` is missing in object literal [1]. [prop-missing]7:18-7:20: Cannot call `getProp` because property `b` is missing in object literal [1] in type argument `K`. [prop-missing]
これらのアクセスをネストできます。
1type Cat = {2 name: string,3 age: number,4 hungry: boolean,5 personality: {6 friendly: boolean,7 hungerLevel: number,8 }9};10
11type Friendly = Cat['personality']['friendly']; // type Friendly = boolean12const isFriendly: Friendly = true; // Pet the cat
オプションのインデックスアクセス型
オプションのインデックスアクセス型は、オプションチェーンのように機能します。これにより、null許容オブジェクト型からプロパティにアクセスできます。以前は
type T = $ElementType<$NonMaybeType<Obj>, 'prop'> | void;
のようにしていましたが、
type T = Obj?.['prop'];
のようにできます。オプションチェーンと同様に、オプションのインデックスアクセス型の結果型にはvoid
が含まれます。ネストされたオプションアクセスの長いチェーンがある場合は、結果の型にvoid
を含めたくない場合は、全体を$NonMaybeType<...>
でラップできます。
例
1type TasksContent = ?{2 tasks?: Array<{3 items?: {4 metadata?: {5 title: string,6 completed: boolean,7 },8 },9 }>,10};11
12type TaskData = TasksContent?.['tasks']?.[number]?.['items']?.['metadata'];
オプションチェーンとオプションのインデックスアクセス型には、小さな違いが1つあります。アクセスするオブジェクト型がnull許容でない場合、オプションチェーンの結果型にはvoid
が含まれません。オプションのインデックスアクセス型では、実装上の理由により、結果型には常にvoid
が含まれます。ただし、オブジェクト型がnull許容でない場合は、オプションのインデックスアクセス型を使用する必要はなく、通常のインデックスアクセス型を使用する必要があります。
導入
インデックスアクセス型を使用するには、構文をサポートするようにインフラストラクチャをアップグレードする必要があります。
flow
とflow-parser
: 0.155prettier
: 2.3.2babel
: 7.14
インデックスアクセス型は、$PropertyType
および$ElementType
ユーティリティ型の代替です。これらのユーティリティ型に既に精通している場合は、簡単な変換ガイドを次に示します。
→$PropertyType<Obj, 'prop'>
Obj['prop']
→$ElementType<Obj, T>
Obj[T]
→$ElementType<$PropertyType<Obj, 'prop'>, T>
Obj['prop'][T]
$ElementType
と$PropertyType
の使用について警告し、代わりにインデックスアクセス型を推奨するESLintルールを作成しました。これには、ほとんどの場合を処理できる自動修正機能が含まれています。このルールをコードベースで有効にして、既存の問題をすべて自動修正するだけです。
eslint-plugin-fb-flow
をインストールし、ESLintプラグインリストにfb-flow
を追加します。次に、ESLint設定でルールを有効にします。
'fb-flow/use-indexed-access-type': 1,