W TypeScript mogę zadeklarować parametr funkcji jako typ funkcji. Czy istnieje sposób „bezpieczny dla typu”, którego mi brakuje? Rozważmy na przykład:
class Foo {
save(callback: Function) : void {
//Do the save
var result : number = 42; //We get a number from the save operation
//Can I at compile-time ensure the callback accepts a single parameter of type number somehow?
callback(result);
}
}
var foo = new Foo();
var callback = (result: string) : void => {
alert(result);
}
foo.save(callback);
Funkcja callback save nie jest bezpieczna dla typu, nadaję jej funkcję callback, w której parametrem funkcji jest ciąg znaków, ale przekazuję jej liczbę i kompiluję bez błędów. Czy mogę ustawić parametr wynikowy w funkcji bezpiecznej dla typu?
Wersja TL; DR: czy w TypeScript istnieje odpowiednik delegata .NET?
typescript
vcsjones
źródło
źródło
(n: number) => any
oznacza jakąś sygnaturę funkcji?number
), ale typ zwrotu nie jest w ogóle ograniczony (może to być dowolna wartość, a nawetvoid
)n
tej składni? Czy same typy danych wejściowych i wyjściowych nie byłyby wystarczające?Oto odpowiedniki TypeScript niektórych popularnych delegatów platformy .NET:
źródło
Action
iFunc
uczestnicy eliminują większość zapotrzebowania na określone typy delegatów i, co ciekawe, dają C # pozory typowego pisania strukturalnego. Minusem tych delegatów jest to, że ich nazwiska nie mają żadnego znaczenia, ale inne zalety na ogół przeważają nad tym. W TypeScript po prostu nie potrzebujemy tych typów. Tak więc byłby anty-wzórfunction map<T, U>(xs: T[], f: Func<T, U>)
. Wolęfunction map<T, U>(xs: T[], f: (x: T) => U)
Zdaję sobie sprawę, że ten post jest stary, ale istnieje bardziej zwarte podejście, które nieco różni się od tego, o co pytano, ale może być bardzo pomocną alternatywą. Można zasadniczo zadeklarować funkcję w linii podczas wywoływania metody (
Foo
„ssave()
w tym przypadku). Wyglądałoby to tak:multipleCallback()
Podejście jest bardzo przydatna dla rzeczy jak połączeń sieciowych, które może uda lub nie. Ponownie zakładając przykład wywołania sieciowego, gdymultipleCallbacks()
jest wywoływany, zachowanie zarówno sukcesu, jak i niepowodzenia można zdefiniować w jednym miejscu, co zapewnia większą przejrzystość dla przyszłych czytników kodów.Ogólnie z mojego doświadczenia wynika, że takie podejście jest bardziej zwięzłe, mniej zagracone i ogólnie bardziej przejrzyste.
Powodzenia wszystkim!
źródło
Z pewnością jest to zgodne z paradygmatem programowania funkcjonalnego.
źródło
inputType
raczej nazwaćreturnType
, prawda? GdzieinputType
jest typ,data
który przekazujesz parametr docallback
funkcji.W TS możemy wpisywać funkcje w następujący sposób:
Rodzaje funkcji / podpisy
Służy do rzeczywistych implementacji funkcji / metod i ma następującą składnię:
Przykład:
Literały typu funkcji
Literały typu funkcji to inny sposób deklarowania typu funkcji. Zazwyczaj są one stosowane w sygnaturze funkcji funkcji wyższego rzędu. Funkcja wyższego rzędu to funkcja, która przyjmuje funkcje jako parametry lub zwraca funkcję. Ma następującą składnię:
Przykład:
źródło
Jeśli najpierw zdefiniujesz typ funkcji, będzie to wyglądać następująco
Bez typu funkcji przy użyciu zwykłej składni właściwości byłoby to:
Jeśli chcesz za pomocą funkcji interfejsu, takiej jak delegaty ogólne c #, byłoby to:
źródło
Oprócz tego, co powiedzieli inni, częstym problemem jest deklarowanie typów tej samej funkcji, która jest przeciążona. Typowym przypadkiem jest metoda EventEmitter on (), która akceptuje wiele rodzajów detektorów. Podobnie może się zdarzyć Podczas pracy z operacjami redux - i tam używasz typu akcji jako literału, aby oznaczyć przeciążenie, W przypadku EventEmitters, używasz typu literału nazwy zdarzenia:
źródło