在Flow中定义子类型的正确方法是什么?

时间:2017-09-23 15:20:08

标签: javascript flowtype

在下面的代码示例中,目的是scrapeMovies函数只接受可序列化的对象。

/* @flow */

type SerializableObjectType = {
  [key: string]: string | number | boolean | $ReadOnlyArray<SerializableObjectType> | SerializableObjectType
};

type GuideType = {|
  rid: string
|};

const guide: GuideType = {
  rid: 'foo'
};

const scrapeMovies = async (guide: SerializableObjectType) => {};

scrapeMovies(guide);

https://flow.org/try/#0PQKgBAAgZgNg9gdzCYAoVAXAngBwKZgDKeATgJYCGMZAXhQEYx4Dy9AVngMYYAquBAXjABvVGDABtANZ4sALjABnDOQB2AcwC6C5WvVgAPmFUBXALb1ShsPThwmFVdYAkAJTwUAJs1UwsAQRISCiwAHmJyKloGJlYObj58AD5rCMpqOkYWdi5eflQAXwBudGx8MABxEzJPPETBEQMxMHJPHRUyDVQDYvROOFVlMHVq2oUqmrr+MCFRcVaFAHIoO0XCktR+wYwlTmD8AFk4ADcyPEUZsApFLFVOMAAKEcmFNKjM2JyE-gBKGZThL1UIo9hRDiczoonqM8D8ikA

我不理解抱怨scrapeMovies被投放guide对象的原因是什么,这对SerializableObjectType的定义不那么严格。

这里定义子类型的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

传递GuideType代替SerializableObjectType是传递更具体类型的实例。默认情况下,Flow仅在函数中允许less specific(逆变/只写)输入。

要实现此目的,您需要将guide参数标记为covariant。通过将对象标记为$ReadOnly<T>,您将有效地将其标记为协变:

Try

type SerializableObjectType = {
  [key: string]: string | number | boolean | $ReadOnlyArray<SerializableObjectType> | SerializableObjectType
};

type GuideType = {|
  rid: string
|};

const guide: GuideType = {
  rid: 'foo'
};

const scrapeMovies = async (guide: $ReadOnly<SerializableObjectType>) => {};

scrapeMovies(guide);

或者,您可以使用对象类型声明中的+标记来标记specific properties as covariant/read-only

Try

type SerializableObjectType = {
  +[key: string]: string | number | boolean | $ReadOnlyArray<SerializableObjectType> | SerializableObjectType
};

type GuideType = {|
  rid: string
|};

const guide: GuideType = {
  rid: 'foo'
};

const scrapeMovies = async (guide: SerializableObjectType) => {};

scrapeMovies(guide);

你为什么要跳舞?为什么输入是协变/逆变/ whateverariant很重要?好吧,如果您尝试将guide参数视为SerializeableObjectType(一般对象图),并且您向number密钥写了rid,那么其他消费者guide对象无法获得他们期望的结果。