2016-12-17 4 views
11

kann ich kein Array von Objekten einem Array von Unionstypen zuweisen. Ich lerne Flow und arbeite daher an einem kleinen Hobbyprojekt mit JavaScript und Flow. Ich habe eine Klasse Foo und eine andere Klasse Bar, die ich in einem Array von Foo Objekte als eine Option im Konstruktor nehmen möchte. Ich möchte aber auch andere Daten für jedes Objekt senden können. Daher möchte ich ein Array haben, bei dem jedes Element entweder ein einfaches Foo Objekt oder ein Foo Objekt ist, das in ein Array oder Objekt eingebettet ist.In Flow

Wenn ich jedoch versuchte, den Code dafür zu schreiben, habe ich einige seltsame Fehler, die ich nicht verstehe, den Grund dafür. Soweit ich das beurteilen kann, gibt es einen Typkonflikt, weil Foo mit der Typen der Union nicht kompatibel ist, aber soweit ich verstehe, sollte es nur mit mindestens einem von ihnen kompatibel sein müssen

...

Hier ist der minimale Code, den ich die genauen Fehler zu reproduzieren, brauchte ich bekam (link to tryflow.org example):

// @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 
}); 

ich folgende Fehlermeldungen erhalten:

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 

gibt es ein intuitiver (oder nicht intuitiver) Grund für diese Fehler?

Antwort

2

Ich denke, BarOptions sollte eigentlich ein Typ Alias ​​anstelle einer Schnittstelle sein. Eine Schnittstelle declares a type that classes can implement. Schnittstellen sind keine Datentypen und sie sollten keine Felder enthalten (die Daten enthalten).

Hier funktioniert alles, wenn wir nur interface BarOptions zu type BarOptions = ändern.

Alternativ können Sie foo ändern eine Getter-Funktion zu werden:

interface BarOptions { 
    foos(): (Foo | [ Foo ] | { foo: Foo })[]; 
} 
2

Glaubst du, es könnte ticket zu diesem offenen Github zusammenhängen? Wenn wir interface mit type ersetzen, bestätigt es:

// @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 }, 
}); 
+0

Können Sie erklären, das funktionieren würde? (Meine Frage ist nicht, wie man es repariert, es versucht zu verstehen, warum das überhaupt ein Problem ist) – Frxstrem

+0

Ich sehe nicht, wie die beiden verschieden sind; Wie ich es verstanden habe, wird 'foo' in beiden Fällen mit demselben Typ (' Foo') deklariert, der einzige Unterschied ist, dass der Typ in der ersten Zeile implizit ist, während er in der zweiten Zeile explizit ist. Wenn ich nicht schrecklich missverstanden habe, wie Flow-Typen funktionieren, sehe ich nicht, wie sich diese anders verhalten würden (obwohl es tatsächlich so scheint). – Frxstrem

+0

Könnte dieses Problem damit zusammenhängen? https://github.com/facebook/flow/issues/1569 –