2017-11-24 4 views
0

Kann jemand erklären, warum dieser Code nicht funktioniert:Argument des Typs 'Barable' ist nicht zuordenbare Parameter vom Typ 'T'

class Fooable { 
    foo: string; 
} 
class Barable extends Fooable { 
    bar: boolean; 
} 

function simplifiedExample<T extends Fooable>(): Array<T> { 
    let list = new Array<T>(); 
     list.push(new Barable()); 
    return list; 
} 

Barable erweitert Fooable. Warum kann ich kein Array zu einem Array hinzufügen, wenn T ein Muss sein muss? Hier Code in playground

EDIT:

das Problem ist, simplifiedExample() ist eine Überschreibung von einer Basisklasse, die Basisklasse nur eine Definition. Da ist ein gemischtes Projekt JS/TS.

sehen: new playground

ich eine Lösung mit einer Besetzung gefunden, aber es scheint nicht wie eine richtige Lösung für mich:

class BarableService extends FooableService { 

    simplifiedExample<T extends Fooable>(): Array<T> { 
     let list = new Array<Fooable>(); 
      list.push(new Barable()); 
     return list as Array<T>; 
    } 
} 

Antwort

0

Die Art Ihrer Array-Liste bekannt ist, sollte es sei Fooable, daher der Rückgabetyp, als Konsequenz.

+0

das funktioniert nicht. [Beispiel] (https://www.typescriptlang.org/play/index.html#src=class%20Fooable%20%7B%0A%20%20%20%20foo%3A%20string%3B%0A%7D% 0% 20% 20%% 20% 20% 20% 20%% 20% 20% 20% 20%% 20% 20% 20% 20% 20% 20% 20% 20% 20% 20% 20% 20% 20% 20% 20% 20% 20% 3A% 20Array% 3CT% 3E% 20% 7B% 0A% 20% 20% 20% 20% 20Liste% 20% 3D% 20new% 20Array% 3CFoable% 3E()% 3B% 0A% 20% 20% 20% 20% 20% 20% 20% 20list.push (neu% 20Barable())% 3B% 0A% 20% 20% 20% 20return% 20list% 3B% 0A% 7D) – razgoolyy

+0

Sie sollten den Rückgabetyp auch in das Array 'Fooable ändern 'wie in der Antwort geschrieben. – NiVeR

+0

Ich kann die Signatur der Methode nicht ändern. Bitte sehen Sie das Update meines Beitrags – razgoolyy

1

Obwohl der Typ T mit Fooable kompatibel ist und die Art Barable ist kompatibel mit Fooable, das bedeutet nicht, Barable mit T kompatibel ist.

Zum Beispiel:

class Bazable extends Fooable { 
    baz: number; 
} 

const result: Bazable[] = simplifiedExample<Bazable>(); 

Das erinnert mich ein wenig an die Philosophie, wie Sie dies ist eine unlogische Schlussfolgerung sehen:

If T (Bazable) is a Fooable 
And Barable is a Fooable 
Then T (Bazable) is a Barable 

Oder ...

If T (Lion) is a Cat 
And Tiger is a cat 
Then T (Lion) is a Tiger 

    Cat 
    /\ 
    / \ 
Lion != Tiger 

Generisches vs Strukturelle

In TypeScript gibt es eine Reihe von Fällen, die dank des Strukturtypsystems ohne Generika gelöst werden können. Sie können feststellen, dass etwa ehrlich Ihre Barable wird gut funktionieren:

function simplifiedExample(): Barable[] { 
    let list: Barable[] = []; 
    list.push(new Barable()); 
    return list; 
} 

Sie brauchen nichts außer einer kompatiblen Struktur für diese Typprüfung passieren:

class Bazable { 
    foo: string; 
    bar: boolean; 
} 

const a: Bazable[] = simplifiedExample(); 

Oder auch:

class Bazable { 
    bar: boolean; 
} 

const a: Bazable[] = simplifiedExample(); 

Und natürlich:

const a: Fooable[] = simplifiedExample(); 

Wenn dies nicht Ihren Anforderungen entspricht, müssen Sie möglicherweise ein Beispiel angeben, in dem Sie einen generischen Typ einführen müssen. Normalerweise wäre dies, wenn Sie innerhalb der Funktion einen neuen T konstruieren möchten, anstatt einen festen Typ.

+0

ok, thx. Generika in TS funktionieren nicht wie in C#. aber was ist mit diesem Beispiel: https://www.typescriptlang.org/play/index.html#src=class%20Fooable%20%7B%0A%20%20%20%20foo%3A%20string%3B%0A % 7D% 0Aclass% 20Barable% 20Extends% 20Foable% 20% 7B% 20% 0A% 20% 20% 20% 20bar% 3A% 20Boolean% 3B% 0A% 7D% 0A% 0Affunktion% 20SimplifiedBeispiel% 3CT% 20Extends% 20Foable% 3E()% 3A% 20Array% 3CT% 3E% 20% 7B% 0A% 20% 20% 20% 20% 20Liste% 20% 3D% 20Neu% 20Array% 3CFußbar% 3E()% 3B% 0A% 20% 20% 20 % 20% 20% 20% 20% 20list.push (neu% 20Barable())% 3B% 0A% 20% 20% 20% 20zurück% 20list% 3B% 0A% 7D – razgoolyy

+0

@razgoolyy kannst du sehen, wenn mein Update über lehnen auf strukturellen Typisierung kann funktionieren - anstatt Generika - funktioniert in Ihrem Fall? – Fenton

+0

thx wieder für Ihre Hilfe. Ich verstehe deinen Vorschlag. aber ich kann die Signatur der Methode nicht ändern. Bitte sehen Sie das Update meines Posts – razgoolyy

0

Wie @Fenton darauf hinweist, kann die Kompatibilität von T und Barable nicht in der Funktion überprüft werden.Wenn Sie eine neue Instanz von T erstellen müssen, können Sie den Konstruktor übergeben:

function simplifiedExample<T extends Fooable>(ctor: new()=> T): Array<T> { 
    let list = new Array<T>(); 
     list.push(new ctor()); 
    return list; 
} 

const result1: Bazable[] = simplifiedExample(Bazable); 
const result2: Barable[] = simplifiedExample(Barable); 
Verwandte Themen