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#のデリゲートのように、カスタムタイプを作成する方がきれいだと思います。
これをどのように行うことができますか?
TypeScriptでは、インターフェイスに呼び出し署名を付けることができます。例では、次のように宣言できます。
interface Greeter {
(message: string): void;
}
function sayHi(greeter: Greeter) {
greeter('Hello!');
}
sayHi((msg) => console.log(msg)); // msg is inferred as string
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;
}
}
5年後、多くのTSバージョンの後に、関数型を宣言するためのより単純なtype
定義を使用していることに気付きました。
type Greeter = (msg: string) => void;
const someGreeter: Greeter = (msg: string) => `Hi there with ${msg}`;
呼び出し可能な式の型定義(これはドラフトで問題ありません。人間にとっては... 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);
私は今公開し、使用します @ 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");