Передача класса метода в качестве параметра в Typescript
Я ищу возможность передать метод класса функции, которая затем может выполнить эту функцию в экземпляре этого класса.
Что-то вроде этого псевдокода: (обратите внимание, что это абстрактный пример)
class Foo {
public somefunc() {
// do some
}
public anyfunc() {
// do any
}
}
function bar(obj: Foo ,func: "Foo.method") { // "that 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
но это касается статических функций, которые я не хочу.
Ответы
Ответ 1
Это не проверяет время компиляции, что функция пришла из 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
Ответ 2
Я предполагаю, что вы ищете какой-то способ для компилятора 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
Ответ 3
Да, объявите функцию следующим образом:
myfunction(action: () => void){
action();
}
Назовите его так: typescript:
myfunction(() => alert("hello"));
Или из javascript:
myfunction(function() { alert("hello"); });
Также вы можете передать метод:
myfunction(this.someMethod);
Ответ 4
Typescript решение 2+
TL; DR: Typescript Игровая площадка, "Репо с демо"
Преимущества:
- Проверка времени компиляции.
- Не позволит вам потерять контекст
this
, если
передача метода экземпляра.
- Не теряйте производительность: не нужно объявлять методы класса как методы экземпляра (например,
public somefunc = () => { return this.prop; }
) - Подробнее....
- Не связывайтесь с прототипом класса.
- Согласованный шаблон подписи: передача обратного вызова в качестве первого arg и
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
.
Вторая часть - это 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 Справочник:
Ответ 5
Javascript разрешил бы это, но не уверен, что это то, что вы хотите?
class Foo {
public someFunc(name:string){
return "Hello, " + name;
}
function bar(funcName: string) {
return eval(funcName);
}
console.log(bar("new Foo().someFunc('erik')"));