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

在下面的代码示例中,目的是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

我不明白flowtype是什么原因抱怨scrapeMovies被送入指南对象,这是一个不太严格的SerializableObjectType定义.

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

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

要使其工作,您需要将指南参数标记为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很重要?好吧,如果您尝试将指南参数视为SerializeableObjectType(一般对象图),并且您为rid键写了一个数字,那么该指南对象的其他使用者将无法获得他们期望的内容.

点赞