Venant d’un arrière-plan C #, je souhaite créer un type de données définissant une signature de fonction. En C #, il s'agit d'une delegate
déclarée comme ceci:
delegate void Greeter (string message);
public class Foo
{
public void SayHi (Greeter g) {
g("Hi!");
}
}
Maintenant, je veux obtenir similaire dans TypeScript. Je sais que TypeScript n'a pas de types de délégués, mais seulement des lambdas. Je suis venu avec quelque chose comme ça:
class Foo {
SayHi (greeter: (msg: String) => void) {
greeter('Hi!');
}
}
Bien que cela fonctionne, je souhaite réutiliser la signature de la méthode (msg:String) => void
plusieurs fois et penser que ce serait plus propre de créer un type personnalisé, comme le délégué en C #.
Des idées comment cela peut être fait?
Dans TypeScript, les interfaces peuvent avoir des signatures d'appel. Dans votre exemple, vous pouvez le déclarer comme ceci:
interface Greeter {
(message: string): void;
}
function sayHi(greeter: Greeter) {
greeter('Hello!');
}
sayHi((msg) => console.log(msg)); // msg is inferred as string
Définition de type pour une expression appelable (ceci est un brouillon correct, pour les humains ... pas un BNF ou quelque chose de formel) :
callableType: (paramsDef) => returnType
paramsDef: MULTIPLE paramDef SEPARATED BY ,
paramDef: EITHER paramName: paramType
OR optionalParamName?: paramTypeWhenDefined
OR ...manyParamName: eachParamType[]
Exemple:
var func = something as ((...x: any[]) => any);
Ensuite vous pouvez:
var result = func("a", "b", 2);
Cinq ans et plus, plusieurs versions de TS plus tard, je me retrouve à utiliser une définition plus simple de type
pour déclarer des types de fonctions:
type Greeter = (msg: string) => void;
const someGreeter: Greeter = (msg: string) => `Hi there with ${msg}`;
Je publie maintenant et utilise @ steelbreeze/delegate ; il a quelques limitations par rapport au délégué C #, en ce sens qu'il est immuable, mais fonctionne bien sinon (et renvoie le résultat de toutes les fonctions appelées).
Il vous permet d'écrire du code tel que:
import { create as delegate } from "@steelbreeze/delegate";
function world(s: string) {
console.log(s + " world");
}
const one = delegate(s => console.log(s + " Hello world"));
const two = delegate(s => console.log(s + " Hello"), world);
one("A");
two("B");
delegate(one, two)("C");