it-swarm.com.de

Implementieren der TypeScript-Schnittstelle mit Signatur ohne Funktion und weiteren Feldern

Wie schreibe ich eine Klasse, die diese TypeScript-Schnittstelle implementiert (und den TypeScript-Compiler zufrieden stellt):

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

Ich sah diese verwandte Antwort: Wie lässt man eine Klasse eine Aufrufsignatur in Typescript implementieren?

Das funktioniert aber nur, wenn die Schnittstelle nur die Signatur der Bare-Funktion hat. Es funktioniert nicht, wenn Sie zusätzliche Mitglieder (wie Funktion text2) implementiert haben.

44
user1147862

Es gibt eine einfache und typsichere Möglichkeit, dies mit ES6 zu tun Object.assign:

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

Schnittpunkttypen, von denen ich glaube, dass sie nicht in TypeScript verfügbar waren, als diese Frage ursprünglich gestellt und beantwortet wurde, sind die geheime Sauce, um die richtige Eingabe zu erzielen.

16
Tom Crockett

Hier ist eine Ausarbeitung zu die akzeptierte Antwort .

Soweit ich weiß, besteht die einzige Möglichkeit, eine Anrufsignatur zu implementieren, in der Verwendung einer Funktion/Methode. Um die restlichen Mitglieder zu implementieren, definieren Sie sie einfach in dieser Funktion. Dies mag Entwicklern aus C # oder Java seltsam erscheinen, aber ich denke, dass es in JavaScript normal ist.

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

Um das gewünschte Ergebnis zu erzielen, müssen Sie das Typsystem umgehen, während Sie die Elemente für die Funktion definieren. Anschließend können Sie das Ergebnis in den Schnittstellentyp umwandeln:

//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 keinen Verschluss verwenden müssen. Sie können Ihre temporäre Variable einfach im selben Bereich wie die resultierende Schnittstellenimplementierung deklarieren. Eine andere Möglichkeit ist, die Schließfunktion zu benennen, um die Lesbarkeit zu verbessern.

Ich halte Folgendes für ein realistischeres Beispiel:

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");
9
Sam