Obecnie mam definicję typu jako:
interface Param {
title: string;
callback: any;
}
Potrzebuję czegoś takiego:
interface Param {
title: string;
callback: function;
}
ale druga nie jest akceptowana.
Obecnie mam definicję typu jako:
interface Param {
title: string;
callback: any;
}
Potrzebuję czegoś takiego:
interface Param {
title: string;
callback: function;
}
ale druga nie jest akceptowana.
Odpowiedzi:
Typ globalny Function
służy temu celowi.
Dodatkowo, jeśli zamierzasz wywołać to wywołanie zwrotne z 0 argumentami i zignorujesz jego wartość zwracaną, typ () => void
pasuje do wszystkich funkcji bez argumentów.
Function
jak pokazano w pierwszym wierszu tej odpowiedzi, i mówiąc, że () => void
preferowany jest akapit drugi (z użyciem typu lub cokolwiek pasującego do przypadku użycia)?
Maszynopis z wersji 1.4 zawiera type
słowo kluczowe, które deklaruje alias typu (analogicznie jak typedef
w C / C ++). Możesz zadeklarować swój typ wywołania zwrotnego w ten sposób:
type CallbackFunction = () => void;
która deklaruje funkcję, która nie przyjmuje argumentów i nic nie zwraca. Funkcja, która pobiera zero lub więcej argumentów dowolnego typu i nic nie zwraca:
type CallbackFunctionVariadic = (...args: any[]) => void;
Możesz na przykład powiedzieć
let callback: CallbackFunctionVariadic = function(...args: any[]) {
// do some stuff
};
Jeśli potrzebujesz funkcji, która pobiera dowolną liczbę argumentów i zwraca cokolwiek (w tym void):
type CallbackFunctionVariadicAnyReturn = (...args: any[]) => any;
Możesz podać niektóre obowiązkowe argumenty, a następnie zestaw dodatkowych argumentów (np. Ciąg, liczbę, a następnie zestaw dodatkowych argumentów) w ten sposób:
type CallbackFunctionSomeVariadic =
(arg1: string, arg2: number, ...args: any[]) => void;
Może to być przydatne w przypadku programów obsługi EventEmitter.
W ten sposób można wpisywać funkcje tak mocno, jak chcesz, chociaż możesz dać się ponieść emocjom i napotkać problemy kombinatoryczne, jeśli spróbujesz dopiąć wszystko za pomocą aliasu typu.
Function
i (...args: any[]) => any
co jest preferowane?
...args: any[]
nie jest bardzo przydatne.
type CallbackFunctionSomeVariadic = (arg1: string, arg2: number, ...args: any[]) => void;
czego szukałem ty.
Oto przykład funkcji, która akceptuje wywołanie zwrotne
const sqk = (x: number, callback: ((_: number) => number)): number => {
// callback will receive a number and expected to return a number
return callback (x * x);
}
// here our callback will receive a number
sqk(5, function(x) {
console.log(x); // 25
return x; // we must return a number here
});
Jeśli nie zależy Ci na wartościach zwrotnych wywołań zwrotnych (większość ludzi nie wie, jak je wykorzystać w jakikolwiek skuteczny sposób), możesz użyć void
const sqk = (x: number, callback: ((_: number) => void)): void => {
// callback will receive a number, we don't care what it returns
callback (x * x);
}
// here our callback will receive a number
sqk(5, function(x) {
console.log(x); // 25
// void
});
Uwaga: podpis użyłem dla callback
parametru ...
const sqk = (x: number, callback: ((_: number) => number)): number
Powiedziałbym, że jest to niedobór TypeScript, ponieważ oczekuje się, że podamy nazwę parametrów wywołania zwrotnego. W tym przypadku użyłem, _
ponieważ nie można go użyć w sqk
funkcji.
Jeśli jednak to zrobisz
// danger!! don't do this
const sqk = (x: number, callback: ((number) => number)): number
Jest poprawny TypeScript, ale będzie interpretowany jako ...
// watch out! typescript will think it means ...
const sqk = (x: number, callback: ((number: any) => number)): number
Tzn. TypeScript pomyśli, że nazwa parametru to number
i domyślny typ to any
. Oczywiście nie to zamierzaliśmy, ale niestety, tak działa TypeScript.
Więc nie zapomnij podać nazw parametrów podczas wpisywania parametrów funkcji ... głupio, jak mogłoby się wydawać.
Możesz zdefiniować typ funkcji w interfejsie na różne sposoby,
export interface IParam {
title: string;
callback(arg1: number, arg2: number): number;
}
export interface IParam {
title: string;
callback: (arg1: number, arg2: number) => number;
}
type MyFnType = (arg1: number, arg2: number) => number;
export interface IParam {
title: string;
callback: MyFnType;
}
Korzystanie jest bardzo proste,
function callingFn(paramInfo: IParam):number {
let needToCall = true;
let result = 0;
if(needToCall){
result = paramInfo.callback(1,2);
}
return result;
}
export interface IParam{
title: string;
callback(lateCallFn?:
(arg1:number,arg2:number)=>number):number;
}
Istnieją cztery abstrakcyjne typy funkcji, których można używać osobno, gdy wiadomo, że funkcja pobierze argument (y) lub nie, zwróci dane lub nie.
export declare type fEmptyVoid = () => void;
export declare type fEmptyReturn = () => any;
export declare type fArgVoid = (...args: any[]) => void;
export declare type fArgReturn = (...args: any[]) => any;
lubię to:
public isValid: fEmptyReturn = (): boolean => true;
public setStatus: fArgVoid = (status: boolean): void => this.status = status;
Aby użyć tylko jednego typu jako dowolnego typu funkcji, możemy połączyć wszystkie typy abstrakcyjne razem, tak jak to:
export declare type fFunction = fEmptyVoid | fEmptyReturn | fArgVoid | fArgReturn;
następnie użyj go w następujący sposób:
public isValid: fFunction = (): boolean => true;
public setStatus: fFunction = (status: boolean): void => this.status = status;
W powyższym przykładzie wszystko jest poprawne. Jednak poniższy przykład użycia jest niepoprawny z punktu widzenia większości edytorów kodu.
// you can call this function with any type of function as argument
public callArgument(callback: fFunction) {
// but you will get editor error if call callback argument like this
callback();
}
Prawidłowe połączenie dla redaktorów wygląda następująco:
public callArgument(callback: fFunction) {
// pay attention in this part, for fix editor(s) error
(callback as fFunction)();
}
Typescript: Jak zdefiniować typ wywołania zwrotnego funkcji używanego w parametrze metody ?
Możesz zadeklarować wywołanie zwrotne jako 1) właściwość funkcji lub 2) metodę :
interface ParamFnProp {
callback: (a: Animal) => void; // function property
}
interface ParamMethod {
callback(a: Animal): void; // method
}
Istnieje istotna różnica w pisaniu od TS 2.6 :
Otrzymujesz silniejsze („dźwiękowe”) typy w trybie --strict
lub --strictFunctionTypes
, gdy deklarowana jest właściwość funkcji . Weźmy przykład:
const animalCallback = (a: Animal): void => { } // Animal is the base type for Dog
const dogCallback = (d: Dog): void => { }
// function property variant
const param11: ParamFnProp = { callback: dogCallback } // error: not assignable
const param12: ParamFnProp = { callback: animalCallback } // works
// method variant
const param2: ParamMethod = { callback: dogCallback } // now it works again ...
Technicznie mówiony, metody są bivariant i właściwości funkcyjne kontrawariantny w swoich argumentach poniżej strictFunctionTypes
. Metody są nadal sprawdzane w sposób bardziej dozwolony (nawet jeśli nie dźwiękowy), aby były nieco bardziej praktyczne w połączeniu z typami wbudowanymi, takimi jak Array
.