TypeScript: передача метода объекта для вызова в качестве аргумента

Недавно я начал работать над игрой в Cocos Creator, которая использует TypeScript/JavaScript в качестве языка, в котором я новичок. Я пытаюсь создать сложный метод обратного вызова, который будет вызывать методы, прикрепленные к массиву объектов.

Вот краткий пример функциональности, которую я надеюсь достичь:

let arr:Base[] = [new Foo(), new Bar(), new FooBar()];

function func(interfaceType, method) {
    arr.forEach(element => {
        if (element instanceof interfaceType){
            console.info(element.method());
        }   
    });
}

func(BarI, bar()); //This should output bar foobar
func(FooI, foo()); //This should output 1 2

И все реализации интерфейса и класса

interface FooI{
    foo():number;
    foo2():string;
}

interface BarI{
    bar():string;
}

class Base { }

class Foo extends Base implements FooI{
    foo(): number {
        return 1;
    }
    foo2(): string {
        return "A";
    }
}

class Bar extends Base implements BarI{
    bar(): string {
        return "bar";
    }
}

class FooBar extends Base implements FooI, BarI{
    foo(): number {
        return 2;
    }
    foo2(): string {
        return "B";
    }
    bar(): string {
        return "foobar";
    }
}

В этом блоке кода много проблем, например, instanceof не работает для интерфейсов, это не большая проблема, я нашел пару обходных путей (не самых элегантных, но не очень большая проблема). Настоящая проблема, с которой я столкнулся, - это вызов метода, я осмотрелся и нашел код для передачи функций/методов в качестве параметра, но он запускает параметр как независимую функцию, а не реализованный метод объекта.

Я получил этот пример, работающий с использованием отражений в Java, если вы хотите увидеть рабочий пример: Ссылка на Pastebin


174
2

Ответы:

К сожалению, вы не можете сделать

interface BarI{
    bar():string;
}

if (element instanceof IBar) ...

поскольку интерфейсы не являются «настоящим» js-кодом. Вы могли бы сделать

class BarI{
    bar(): string {
        ...
    }
}

var element = new IBar()

if (element instanceof IBar) ...

Надеюсь, это поможет! Здесь тоже есть полезная информация


Решено

Спасибо Наркеку Дадуряну за ответ. я закончил тем, что сделал

let arr:Base[] = [new Foo(), new Bar(), new FooBar()];

function func(methodName) {
    arr.forEach(element => {
        if (element[methodName] !== undefined){
            console.info(element[methodName]());
        }   
    });
}

func("bar"); //This correctly output bar foobar
func("foo"); //This correctly output 1 2

Это также избавляет от необходимости проверять наличие интерфейсов, что хорошо, потому что имена методов не перекрываются при вызове соответствующих методов.