2013-05-12 4 views
27

Jak napisać klasy, która implementuje ten interfejs maszynopis (i utrzymuje kompilator maszynopis happy):interfejs wykonawcze maszynopis z gołą podpisu Function Plus innych dziedzinach

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

Widziałem ten powiązany odpowiedź: How to make a class implement a call signature in Typescript?

Ale działa to tylko wtedy, gdy interfejs ma tylko podpis funkcji bare. Nie działa, jeśli masz zaimplementowanych dodatkowych członków (na przykład tekst funkcyjny2).

+0

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

+0

Krótka odpowiedź brzmi: "zajęcia nie pasują do tego interfejsu" wymienione w pytaniu, które łączysz http://stackoverflow.com/a/12770145/390330 – basarat

Odpowiedz

32

Klasa nie może zaimplementować wszystkiego, co jest dostępne w interfejsie maszynopisu. Dwa pierwszorzędne przykłady to podpisy na żądanie i operacje indeksu, np. : Implement an indexible interface

Powodem jest to, że interfejs jest zaprojektowany przede wszystkim do opisywania wszystkiego, co mogą zrobić obiekty JavaScript. Dlatego musi być naprawdę solidny. Klasa TypeScript jest jednak zaprojektowana tak, aby reprezentować dziedziczenie prototypowe w sposób bardziej konwencjonalny/łatwy do zrozumienia/łatwy do wpisania.

Nadal można utworzyć obiekt, który następuje tego interfejsu:

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

Oto opracowanie na the accepted answer.

O ile mi wiadomo, jedynym sposobem na wykonanie podpisu rozmówcy jest użycie funkcji/metody. Aby zaimplementować pozostałe elementy, po prostu zdefiniuj je na tej funkcji. Może to wydawać się dziwne dla programistów pochodzących z C# lub Java, ale myślę, że jest to normalne w JavaScript.

W języku JavaScript byłoby to proste, ponieważ można po prostu zdefiniować funkcję, a następnie dodać członków. Jednak system typu TypeScript nie pozwala na to, ponieważ w tym przykładzie Function nie definiuje członka text2.

więc do osiągnięcia rezultatu, który ma, trzeba ominąć system typu podczas definiowania użytkowników na temat funkcji, a następnie można rzutować wynik typu interfejsu:

//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 

pamiętać, że nie trzeba używać zamknięcia. Można po prostu zadeklarować zmienną tymczasową w tym samym zakresie, co wynikowa implementacja interfejsu. Inną opcją jest nazwanie funkcji zamknięcia w celu poprawy czytelności.

Oto, co moim zdaniem jest bardziej realistyczny przykład:

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

Jest łatwym i typu bezpieczny sposób to zrobić z Object.assign ES6 za:

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

rodzaju skrzyżowania, które don” Sądzę, że były dostępne w TypeScript, gdy pytanie to zostało pierwotnie zadane i udzielono na nie odpowiedzi, są sekretnym sposobem na prawidłowe pisanie.

+0

To nie jest całkiem bezpieczne, ponieważ 'Object.assign'' zwraca' 'any''. – Flavien

+1

W aktualnej wersji TS jest to 'przypisz (miejsce docelowe: T, źródło: U): T & U' –

+0

@Flavien bieżące podpisy wyglądają tak: https://github.com/Microsoft/TypeScript/blob/master /lib/lib.es6.d.ts#L4438 –

Powiązane problemy