フローの一般的な制約
Flow には、ジェネリック関数またはクラスを作成したいが、型引数として渡すことができるものを制限したい場合があります。
一般的な制約が役立つ場合
Mapをラップするクラスがあるが、挿入する前に浅いコピーを作成するとします。
class ShallowMap<T> {
map: Map<string, T>;
constructor() {
this.map = new Map();
}
get(key: string) {
return this.map.get(key);
}
set(key: string, value: T) {
// Make a shallow copy. Flow will give an error on this line.
const copy = {...value};
this.map.set(key, copy);
}
}
フローではこれを行うことはできません。オブジェクトを広げることはできますが、他のタイプではできないためです。
// This works.
const spreadEmptyObject = {...Object.create(null)};
const spreadObjectWithProperty = {...{id: 2}};
// This doesn't.
const spreadNumber = {...0};
const spreadString = {...''};
そして、T
がオブジェクトでなければならないということは何もありません。
`T`はオブジェクトでなければならないという何かを追加する
とても簡単です。 ジェネリック型宣言の後にコロンと制約型を追加するだけです。
// `T` has to be an object.
class ShallowMap<T: Object> {
map: Map<string, T>;
constructor() {
this.map = new Map();
}
get(key: string) {
return this.map.get(key);
}
set(key: string, value: T) {
// Flow is okay with this line now.
const copy = {...value};
this.map.set(key, copy);
}
}
より具体的な制約
制約はより具体的にすることができ、いくつかの基準に適合するため、ジェネリック型とのより複雑な相互作用が可能になります。 たとえば、T
のプロパティを使用してキーを決定する一般的なマップ:
type Keyable = {
key: string,
};
// `T` has a string property called `key`.
class AutoKeyMap<T: {key: string}> {
map: Map<string, T>;
constructor() {
this.map = new Map();
}
get(key: string) {
return this.map.get(key);
}
set(value: T) {
// Since `T` has a string property `key`, we can access it.
const key = value.key;
this.map.set(key, value);
}
}