2017-11-14 1 views
0

Im folgenden Beispiel kann der TypScript-Compiler nicht zu Kind direkt übertragen. Tatsächlich ist es möglich, Zwischenvariable Temp oder Double Casting zu verwenden, wie in den kommentierten Zeilen gezeigt. Ist es ein Fehler oder gibt es eine logische Erklärung? Der Link zu playgroundTyposkript: downcast auf "this" ist nicht möglich

class Parent { 
     prop: string = null; 
     castToChild(): Child{ 
      let temp: Parent = this; 
      return this as Child; 
      //return temp as Child; 
      //return this as Parent as Child; 
     } 
    } 
    class Child extends Parent 
    { 
     otherProp: string = null; 
    } 

Antwort

0

Sie können direkt keine Parent zu einem Child einfach werfen, da der Compiler keine Möglichkeit hat, zu wissen, dass Ihre Parent Instanz wirklich ein Child ist. Verwenden Sie einen Typ-Schutz anstelle eines Darstellers:

class Parent { 
    prop: string|null = null; 
    isChild(): this is Child { 
     return (this as any).otherProp !== undefined; 
    } 
} 
class Child extends Parent 
{ 
    otherProp: string|null = null; 
} 

function test(p: Parent) { 
    if (p.isChild()) { 
    console.log(p.otherProp); 
    } 
} 

Im Inneren des bewachten if nun der Compiler weiß, dass p ein Child ist, außerhalb noch p ist nur ein Parent.

Oder noch besser, überschreiben die Wache in der Unterklasse und Sie können dabei jede Schublade gesteckt gar vermeiden:

class Parent { 
    prop: string|null = null; 
    isChild(): this is Child { 
     return false; 
    } 
} 
class Child extends Parent 
{ 
    otherProp: string|null = null; 
    isChild(): this is Child { return true; } 
} 

function test(p: Parent) { 
    if (p.isChild()) { 
    console.log(p.otherProp); 
    } 
} 

Sie sind richtig, aber, dass ich nicht die Frage beantwortet haben, ob dies ein Fehler oder vorsätzlichen seitens der Typescript-Autoren. Meine Vermutung ist, dass sie versuchen, mögliche Fehler zu finden, aber ich habe keine Erklärung für genau dieses Verhalten gefunden, das es bestätigen oder leugnen würde.

Eine weitere Möglichkeit, Ihre Original-Code Arbeit machen kann, ist ausdrücklich die Art der this im castToChild Methode Typoskript zu sagen:

class Parent { 
    prop: string|null = null; 

    castToChild(this: Parent): Child{ 
     return this as Child; 
    } 
} 
class Child extends Parent 
{ 
    otherProp: string|null = null; 
} 

function foo() { 
    let p: Parent = new Child(); 
    let c = p.castToChild(); 
    console.log(c.otherProp); 
} 

Dies ist immer noch wirklich nur die doppelte Besetzung zu tun, sieht aber vielleicht ein bisschen sauberer . Es zeigt jedoch immer noch die Fremdheit des Verhaltens, da ohne den expliziten this Parameter this vom Typ Parent, aber nicht direkt gießbar ist, mit dem expliziten Parameter können Sie es umsetzen.

+0

Sorry, aber ich sehe Ihre Lösung als zu kompliziert. Meine Problemumgehungen mit Zwischenvariablen oder Double-Cast sind viel kürzer und erfordern keinen zusätzlichen Code. Sie erzeugen jedoch nur unnötiges syntaktisches Rauschen. Ich stimme zu, dass der Compiler nicht weiß, dass das Elternteil wirklich ein Kind ist, aber das ist genau der Grund, warum ich Casting mache - um zu sagen, dass ich es besser weiß. –

+0

Interessante Ansicht. Sicherlich liegt der Sinn von Typoskript darin, dass Sie es manchmal nicht besser wissen und der Compiler Ihnen sagen kann, wenn Sie einen Fehler machen. Wenn Sie immer besser als der Compiler wissen, warum nicht einfach Javascript verwenden und sich nicht um diese Typen kümmern müssen? – Duncan

+0

Es tut mir leid, wenn meine Antwort dich irgendwie beleidigt hat, es war sicherlich nicht meine Absicht. Aber dein Vorschlag ist es immer noch nicht die Antwort auf meine Frage: "Warum akzeptiert der TS-Compiler die Besetzung als Doppelbesetzung oder mit der Zwischenvariable, aber nicht auf dem direkten Weg?" Gehen Sie den gleichen Weg mit zwei Schritten statt einer ist, was ich "syntaktischen Lärm" genannt –

Verwandte Themen