Attualmente ho la definizione del tipo come:
interface Param {
title: string;
callback: any;
}
Ho bisogno di qualcosa del tipo:
interface Param {
title: string;
callback: function;
}
ma il secondo non viene accettato.
Attualmente ho la definizione del tipo come:
interface Param {
title: string;
callback: any;
}
Ho bisogno di qualcosa del tipo:
interface Param {
title: string;
callback: function;
}
ma il secondo non viene accettato.
Risposte:
Il tipo globale Function
serve a questo scopo.
Inoltre, se si intende richiamare questo callback con 0 argomenti e si ignora il valore restituito, il tipo () => void
corrisponde a tutte le funzioni che non accettano argomenti.
Function
come mostrato nella prima riga di questa risposta, e dici che il secondo paragrafo (usando il tipo di () => void
o qualunque cosa corrisponda al caso d'uso) è preferito?
Typescript da v1.4 ha la type
parola chiave che dichiara un alias di tipo (analogo a a typedef
in C / C ++). Puoi dichiarare il tuo tipo di callback così:
type CallbackFunction = () => void;
che dichiara una funzione che non accetta argomenti e non restituisce nulla. Una funzione che accetta zero o più argomenti di qualsiasi tipo e non restituisce nulla sarebbe:
type CallbackFunctionVariadic = (...args: any[]) => void;
Quindi puoi dire, ad esempio,
let callback: CallbackFunctionVariadic = function(...args: any[]) {
// do some stuff
};
Se si desidera una funzione che accetta un numero arbitrario di argomenti e restituisce qualsiasi cosa (incluso vuoto):
type CallbackFunctionVariadicAnyReturn = (...args: any[]) => any;
È possibile specificare alcuni argomenti obbligatori e quindi una serie di argomenti aggiuntivi (ad esempio una stringa, un numero e quindi una serie di argomenti aggiuntivi) in questo modo:
type CallbackFunctionSomeVariadic =
(arg1: string, arg2: number, ...args: any[]) => void;
Questo può essere utile per cose come i gestori EventEmitter.
In questo modo le funzioni possono essere digitate quanto più ti piace, sebbene tu possa lasciarti trasportare e incorrere in problemi combinatori se provi a inchiodare tutto con un alias di tipo.
Function
e (...args: any[]) => any
cosa è preferito?
...args: any[]
non è molto utile.
type CallbackFunctionSomeVariadic = (arg1: string, arg2: number, ...args: any[]) => void;
quello che stavo cercando, ty.
Ecco un esempio di una funzione che accetta un callback
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
});
Se non ti interessano i valori di ritorno dei callback (la maggior parte delle persone non sa come utilizzarli in modo efficace), puoi utilizzare 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
});
Nota, la firma che ho usato per il callback
parametro ...
const sqk = (x: number, callback: ((_: number) => number)): number
Direi che si tratta di un difetto di TypeScript perché ci si aspetta che fornisca un nome per i parametri di callback. In questo caso l'ho usato _
perché non è utilizzabile all'interno disqk
funzione.
Tuttavia, se lo fai
// danger!! don't do this
const sqk = (x: number, callback: ((number) => number)): number
È TypeScript valido , ma verrà interpretato come ...
// watch out! typescript will think it means ...
const sqk = (x: number, callback: ((number: any) => number)): number
Vale a dire, TypeScript penserà che il nome del parametro sia number
e il tipo implicito siaany
. Ovviamente non è quello che intendevamo, ma purtroppo è così che funziona TypeScript.
Quindi non dimenticare di fornire i nomi dei parametri durante la digitazione dei parametri della funzione ... stupido come potrebbe sembrare.
È possibile definire un tipo di funzione nell'interfaccia in vari modi,
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;
}
L'uso è molto semplice,
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;
}
Esistono quattro tipi di funzioni astratte, puoi usarle separatamente quando sai che la tua funzione prenderà un argomento o meno, restituirà un dato o meno.
export declare type fEmptyVoid = () => void;
export declare type fEmptyReturn = () => any;
export declare type fArgVoid = (...args: any[]) => void;
export declare type fArgReturn = (...args: any[]) => any;
come questo:
public isValid: fEmptyReturn = (): boolean => true;
public setStatus: fArgVoid = (status: boolean): void => this.status = status;
Per utilizzare un solo tipo come qualsiasi tipo di funzione, possiamo combinare tutti i tipi astratti insieme, in questo modo:
export declare type fFunction = fEmptyVoid | fEmptyReturn | fArgVoid | fArgReturn;
quindi usalo come:
public isValid: fFunction = (): boolean => true;
public setStatus: fFunction = (status: boolean): void => this.status = status;
Nell'esempio sopra tutto è corretto. Ma l'esempio di utilizzo in basso non è corretto dal punto di vista della maggior parte degli editor di codice.
// 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();
}
La chiamata corretta per i redattori è così:
public callArgument(callback: fFunction) {
// pay attention in this part, for fix editor(s) error
(callback as fFunction)();
}
Dattiloscritto: come definire il tipo per un callback di funzione utilizzato in un parametro di metodo ?
È possibile dichiarare il callback come 1) proprietà della funzione o 2) metodo :
interface ParamFnProp {
callback: (a: Animal) => void; // function property
}
interface ParamMethod {
callback(a: Animal): void; // method
}
Esiste un'importante differenza di battitura rispetto a TS 2.6 :
Si ottengono tipi più forti ("audio") in --strict
o --strictFunctionTypes
mode, quando viene dichiarata una proprietà di funzione . Facciamo un esempio:
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 ...
Tecnicamente parlato, i metodi sono bivariant e le proprietà funzionali contravariant nei loro argomenti sotto strictFunctionTypes
. I metodi sono ancora controllati in modo più permissivo (anche se non sano) per essere un po 'più pratico in combinazione con tipi integrati comeArray
.