web-dev-qa-db-ja.com

Typescriptでデリゲート型を宣言する

C#のバックグラウンドから来て、関数シグネチャを定義するデータ型を作成したいと思います。 C#では、これは次のように宣言されたdelegateです:

delegate void Greeter (string message);

public class Foo
{
    public void SayHi (Greeter g) {
        g("Hi!");
    }
}

ここで、TypeScriptで同様の機能を実現したいと思います。 TypeScriptにはデリゲート型はなく、ラムダしかありません。私はこのようなものを思いつきました:

class Foo {
    SayHi (greeter: (msg: String) => void) {
        greeter('Hi!');
    }
}

これは機能しますが、メソッドシグネチャ(msg:String) => void数回、C#のデリゲートのように、カスタムタイプを作成する方がきれいだと思います。

これをどのように行うことができますか?

52
Dynalon

TypeScriptでは、インターフェイスに呼び出し署名を付けることができます。例では、次のように宣言できます。

interface Greeter {
    (message: string): void;
}

function sayHi(greeter: Greeter) {
    greeter('Hello!');
}

sayHi((msg) => console.log(msg)); // msg is inferred as string
64
Ryan Cavanaugh

type alias を使用して、デリゲートのようなものを作成できます。

type MyDelegate = (input: string) => void;

これは、デリゲートがC#で行うように、関数ポインターの型名を定義します。次の例では、ジェネリック型パラメーターと組み合わせて使用​​しています。

type Predicate<T> = (item: T) => boolean;

export class List<T> extends Array<T> {
    constructor(...items: T[]){
        super();
        for(let i of items || []){
            this.Push(i);
        }
    }
    public hasAny(predicate?: Predicate<T>): boolean {
        predicate = predicate || (i => true)
        for(let item of this) {
            if(predicate(item)) return true;
        }
        return false;
    }
}
27
Orphid

5年後、多くのTSバージョンの後に、関数型を宣言するためのより単純なtype定義を使用していることに気付きました。

type Greeter = (msg: string) => void;
const someGreeter: Greeter = (msg: string) => `Hi there with ${msg}`;
3
Dynalon

呼び出し可能な式の型定義(これはドラフトで問題ありません。人間にとっては... BNFや正式なものではありません)

callableType: (paramsDef) => returnType

paramsDef:    MULTIPLE paramDef SEPARATED BY ,

paramDef:     EITHER   paramName: paramType
                  OR   optionalParamName?: paramTypeWhenDefined
                  OR   ...manyParamName: eachParamType[]

例:

var func = something as ((...x: any[]) => any);

その後、次のことができます。

var result = func("a", "b", 2);
1
Miguel Angelo

私は今公開し、使用します @ steelbreeze/delegate ; C#デリゲートと比較していくつかの制限があり、不変ですが、それ以外の場合は適切に機能します(呼び出されたときに、呼び出されたすべての関数から結果を返します)。

次のようなコードを記述できます。

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