クラスメソッドを関数に渡し、そのクラスのインスタンスでその関数を実行できる可能性を探しています。その擬似コードのようなもの:(これは抽象的な例であることに注意してください)
class Foo {
public somefunc() {
// do some
}
public anyfunc() {
// do any
}
}
function bar(obj: Foo ,func: "Foo.method") { // "that's what im looking for"
obj.func();
}
bar(new Foo(), Foo.somefunc); // do some
bar(new Foo(), Foo.anyfunc); // do any
これを行う可能性はありますか?
私はそのようなことをしている可能性があることを知っています:
class Foo {
static somefunc(fooObj: Foo) {
// do some
}
static anyfunc(fooObj: Foo) {
// do any
}
}
interface func {
(fooObj: Foo);
}
function bar(obj: Foo, fn: func) {
fn(obj);
}
bar(new Foo(), Foo.somefunc); // do some
bar(new Foo(), Foo.anyfunc); // do any
しかし、それは私が望んでいない静的関数を伴います。
これは、関数がFoo
から来たことをコンパイル時にチェックしませんが、残りは行います:
class Foo {
public somefunc() {
// do some
}
public anyfunc() {
// do any
}
}
function bar(obj: Foo ,func: () => void) {
func.call(obj);
}
bar(new Foo(), Foo.prototype.somefunc); // do some
bar(new Foo(), Foo.prototype.anyfunc); // do any
TL; DR: TypeScript Playground 、 デモ付きのレポ
利点:
this
コンテキストを失ってはいけません。public somefunc = () => { return this.prop; }
)- 詳細 。thisArg
を渡します(例: Array.prototype.map() )。次のコードを検討してください。
class Foo {
private result: number = 42;
public func(this: Foo): number {
return this.result;
}
}
function action(): void {
console.log("Hello world!");
}
function bar(callbackFn: (this: void) => any, thisArg?: undefined): any;
function bar<T>(callbackFn: (this: T) => any, thisArg: T): any;
function bar<T, TResult>(callbackFn: (this: T) => TResult, thisArg: T): TResult {
return callbackFn.call(thisArg);
}
const foo = new Foo();
bar(action); // success
bar(foo.func); // ERROR: forgot to pass `thisArg`
bar(foo.func, foo); // success
Foo#func
の署名に注意を向けます。
public func(this: Foo): number
この関数は、クラスのインスタンスのコンテキストで呼び出す必要があることを示しています。これは、this
コンテキストを失わないソリューションの最初の部分です。
2番目の部分は、bar
関数のオーバーロードです。
function bar(callbackFn: (this: void) => any, thisArg?: undefined): any;
function bar<T>(callbackFn: (this: T) => any, thisArg: T): any;
function bar<T, TResult>(callbackFn: (this: T) => TResult, thisArg: T): TResult
これにより、ジェネリック関数とインスタンスメソッドを渡すことができます。
これらのトピックの詳細については、TypeScriptハンドブックをご覧ください。
TypeScriptコンパイラが特定の関数がFooに存在することを強制する方法を探していると思いますか?残念ながら、それを行う方法はないと思います。別のTypeScriptの第一人者がここに来て、より具体的に答えることができるかもしれませんが、これが最も近いと確信しています。
class Foo {
constructor(private name:string) { }
public somefunc() {
console.log("someFunc called on", this.name);
}
public anyfunc() {
console.log("anyFunc called on", this.name);
}
}
function bar(obj: Foo, func: string) {
if (obj[func] && obj[func] instanceof Function) {
obj[func]();
} else {
throw new Error("Function '" + func + "' is not a valid function");
}
}
bar(new Foo("foo1"), "somefunc"); // output: 'somefunc called on foo1'
bar(new Foo("foo2"), "anyfunc"); // output: 'anyfunc called on foo1'
bar(new Foo("foo3"), "badFunction"); // throws: Error: Function 'badFunction' is not a valid function
はい、次のような関数を宣言します:
myfunction(action: () => void){
action();
}
TypeScriptから次のように呼び出します。
myfunction(() => alert("hello"));
またはjavascriptから:
myfunction(function() { alert("hello"); });
メソッドを渡すこともできます:
myfunction(this.someMethod);
Javascriptはこれを許可しますが、それがあなたが望むものかどうかはわかりませんか?
class Foo {
public someFunc(name:string){
return "Hello, " + name;
}
function bar(funcName: string) {
return eval(funcName);
}
console.log(bar("new Foo().someFunc('erik')"));