web-dev-qa-db-fra.com

Déclarer un type de délégué en dactylographie

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?

44
Dynalon

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
58
Ryan Cavanaugh

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);
2
Miguel Angelo

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}`;
0
Dynalon

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");
0
Mesmo