2013-05-12 2 views
27

Wie schreibe ich eine Klasse, die diesen Typoskript-Schnittstelle implementiert (und hält den Typoskript Compiler glücklich):Implementierung Typoskript Schnittstelle mit bloßer Funktionssignatur und anderen Feldern

interface MyInterface { 
    (): string; 
    text2(content: string); 
} 

ich diese ähnliche Antwort sah: How to make a class implement a call signature in Typescript?

Das funktioniert aber nur, wenn die Schnittstelle nur die bare Funktionssignatur hat. Es funktioniert nicht, wenn Sie zusätzliche Mitglieder (wie Funktion text2) haben, die implementiert werden sollen.

+0

http://stackoverflow.com/questions/16248812/implement-an-indexible-interface#comment23254752_16248812 – basarat

+0

Kurze Antwort ist "Klassen können diese Schnittstelle nicht übereinstimmen" in der Frage erwähnt, die Sie http://StackOverflow.com verlinkt/a/12770145/390330 – basarat

Antwort

32

Eine Klasse kann nicht alles implementieren, was in einer Typoskript-Schnittstelle verfügbar ist. Zwei Hauptbeispiele sind aufrufbare Signaturen und Indexoperationen, z. : Implement an indexible interface

Der Grund ist, dass eine Schnittstelle in erster Linie entworfen ist, um alles zu beschreiben, was JavaScript-Objekte tun können. Daher muss es wirklich robust sein. Eine TypeScript-Klasse ist jedoch so konzipiert, dass sie die Prototypvererbung in einer konventionelleren/leicht verständlichen/einfach zu typisierenden Weise darstellt.

Sie können immer noch ein Objekt erstellen, die diese Schnittstelle folgt:

interface MyInterface { 
    (): string; 
    text2(content: string); 
} 

var MyType = ((): MyInterface=>{ 
    var x:any = function():string { // Notice the any 
     return "Some string"; // Dummy implementation 
    } 
    x.text2 = function(content:string){ 
     console.log(content); // Dummy implementation 
    } 
    return x; 
} 
); 
9

Hier ist eine Weiterentwicklung auf the accepted answer.

Soweit ich weiß, ist die einzige Möglichkeit, eine Call-Signatur zu implementieren, die Verwendung einer Funktion/Methode. Um die restlichen Elemente zu implementieren, definieren Sie sie einfach in dieser Funktion. Das mag für Entwickler aus C# oder Java seltsam erscheinen, aber ich denke, das ist normal in JavaScript.

In JavaScript wäre dies einfach, weil Sie einfach die Funktion definieren und dann die Mitglieder hinzufügen können. Das Typskript-Typsystem lässt dies jedoch nicht zu, da Function in diesem Beispiel kein text2-Element definiert.

So das gewünschte Ergebnis zu erzielen, müssen Sie die Art System umgehen, während Sie die Mitglieder auf die Funktion, zu definieren und dann können Sie das Ergebnis an den Interface-Typ gegossen:

//A closure is used here to encapsulate the temporary untyped variable, "result". 
var implementation = (() => { 
    //"any" type specified to bypass type system for next statement. 
    //Defines the implementation of the call signature. 
    var result: any =() => "Hello"; 

    //Defines the implementation of the other member. 
    result.text2 = (content: string) => { }; 

    //Converts the temporary variable to the interface type. 
    return <MyInterface>result; 
})(); //Invokes the closure to produce the implementation 

Beachten Sie, dass Sie brauche keinen Verschluss. Sie könnten Ihre temporäre Variable einfach im selben Umfang wie die resultierende Schnittstellenimplementierung deklarieren. Eine andere Möglichkeit besteht darin, die Schließfunktion zu benennen, um die Lesbarkeit zu verbessern.

Hier ist, was ich denke, ein realistischeres Beispiel ist:

interface TextRetriever { 
    (): string; 
    Replace(text: string); 
} 

function makeInMemoryTextRetriever(initialText: string) { 
    var currentText = initialText; 
    var instance: any =() => currentText; 
    instance.Replace = (newText: string) => currentText = newText; 

    return <TextRetriever>instance; 
} 

var inMemoryTextRetriever = makeInMemoryTextRetriever("Hello"); 
6

Es gibt eine einfache und typsichere Art und Weise dies mit ES6 der Object.assign zu tun:

const foo: MyInterface = Object.assign(
    // Callable signature implementation 
() => 'hi', 
    { 
    // Additional properties 
    text2(content) { /* ... */ } 
    } 
) 

Kreuzung Typen, die ich don‘ Wenn diese Frage ursprünglich in TypeScript gestellt und beantwortet wurde, gibt es die geheime Soße, um das Tippen richtig zu machen.

+0

Dies ist nicht ganz sicher, da '' Object.assign'' 'any'' zurückgibt. – Flavien

+1

In der aktuellen Version von TS ist es 'assign (Ziel: T, Quelle: U): T & U' –

+0

@Flavien die aktuellen Signaturen wie folgt aussehen: https://github.com/Microsoft/TypeScript/blob/master /lib/lib.es6.d.ts#L4438 –

Verwandte Themen