Невозможно присвоить массив объектов массиву типов объединения в потоке
Я изучаю Flow, и поэтому я работаю над небольшим хобби-проектом с JavaScript и Flow. У меня есть класс Foo
и другой класс Bar
, который я хочу взять в массив объектов Foo
в качестве опции в конструкторе. Тем не менее, я также хочу, чтобы иметь возможность отправлять некоторые другие данные для каждого такого объекта, и поэтому я хочу иметь массив, где каждый элемент является либо простым объектом Foo
, либо объектом Foo
, завернутым в массив или объект.
Однако, когда я попытался написать код для этого, у меня появились некоторые странные ошибки, которые я не понимаю. Насколько я могу судить, он считает, что существует конфликт типа, поскольку Foo
несовместим со всеми типами объединения, но насколько я понимаю, он должен быть совместим хотя бы с одним из них...
Здесь минимальный код мне нужно было воспроизвести точные ошибки, которые я получил (ссылка на пример tryflow.org):
// @flow
class Foo { }
interface BarOptions {
foos: ( Foo | [ Foo ] | { foo: Foo } )[]; // line 6
}
class Bar {
constructor(options?: BarOptions) { }
}
const foo: Foo = new Foo();
const bar = new Bar({
foos: [ foo ], // line 16
});
Я получаю следующие ошибки:
Line 6:
tuple type: This type is incompatible with Foo
object type: This type is incompatible with Foo
Line 16:
tuple type: This type is incompatible with Foo
object type: This type is incompatible with Foo
Есть ли интуитивная (или неинтуитивная) причина этих ошибок?
Ответы
Ответ 1
Думаю, что BarOptions
должен быть псевдонимом типа вместо интерфейса. Интерфейс объявляет тип, который классы могут реализовать. Интерфейсы не являются типами данных, и у них не должно быть полей (содержащих данные).
Здесь все работает, если мы просто изменим interface BarOptions
на type BarOptions =
.
В качестве альтернативы вы можете изменить foo
, чтобы стать функцией getter:
interface BarOptions {
foos(): ( Foo | [ Foo ] | { foo: Foo } )[];
}
Ответ 2
Считаете ли вы, что это может быть связано с этим открытым сообщением Github ? Если мы заменим interface
на type
, он проверяет:
// @flow
class Foo { }
type BarOptions ={
foos:
Class<Foo> |
Foo |
Foo[] |
{ foo: Foo }
}
class Bar {
constructor(options?: BarOptions) { }
}
const foo: Foo = new Foo();
const bar = new Bar({
foos: Foo,
// foos: foo,
// foos: [foo],
// foos: { foo: foo },
});