Получение объектов по типу в TypeScript с загрузкой AMD

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

  getItemsByType<T>(type: string): T[] {
     var results: T[] = [];
     for (var item in this) {
        if (typeof this[item] === type) {
           results.push(this[item]);
        }
     }
     return results;
  }

Однако мой класс Foo () просто возвращается как объект typeof.

  getItemsByType<T>(type: string): T[] {
     var results: T[] = [];
     for (var item in this) {
        if (this[item] instanceof type) {
           results.push(this[item]);
        }
     }
     return results;
  }

Это просто не работает, я не могу использовать instanceof без фактического class. Однако я использую загрузчик AMD (dojo), поэтому у меня не может быть легко доступного конструктора из этого одинокого метода.

В моем конкретном случае у меня есть массив базового типа, от которого наследуются многие классы для своих определений. Позже мне нужно вытащить из него определенный тип. Если это невозможно, мне может потребоваться также начать хранение по типу.

Любые идеи? Спасибо.


person Tim    schedule 05.08.2013    source источник


Ответы (2)


Типы TypeScript не выживают в процессе компиляции - они стираются, поэтому все ваши модули и классы являются объектами во время выполнения.

Это означает, что вам нужно прибегнуть к JavaScript, чтобы получить имя объекта во время выполнения (или добавить свойство для каждого класса, которое сообщает вам его тип).

Пример ниже взят непосредственно из статьи, и предостережения в том, что вы получаете только локальное имя - вы не знаете полный путь (например, Module.Module.ClassName):

class Describer {
    static getName(inputClass) { 
        var funcNameRegex = /function (.{1,})\(/;
        var results = (funcNameRegex).exec((<any> inputClass).constructor.toString());
        return (results && results.length > 1) ? results[1] : "";
    }
}
class Example {
}
class AnotherClass extends Example {
}
var x = new Example();
var y = new AnotherClass();
alert(Describer.getName(x)); // Example
alert(Describer.getName(y)); // AnotherClass
person Fenton    schedule 05.08.2013

Попробуйте что-нибудь вроде:

interface NewableClass { new(); }

getItemsByType<T extends NewableClass>(type: T): T[] {
     var results: T[] = [];
     for (var item in this) {
        if (this.hasOwnProperty(item) && this[item] instanceof type) {
           results.push(this[item]);
        }
     }
     return results;
}

Он указывает, что type должно быть "новым". Например, при использовании dijit в качестве типа вы будете использовать его как xxx.getItemsByType(dijit.form.TextBox);

Если вы не хотите создавать новый интерфейс, вы также можете:

getItemsByType<T extends Function>(type: T)

В JavaScript класс - это действительно функция. В проекте LINQ-to-TypeScript метод ofType определен именно таким образом.

Кроме того, если вы используете Dojo, ознакомьтесь с моим проектом Dojo-TypeScript. Это незавершенная работа, но отчасти ее можно использовать.

person Stephen Chung    schedule 06.08.2013
comment
Также обратите внимание на hasOwnProperty, который вы забыли. Обычно рекомендуется объединить этот вызов в цикл for ... in. - person Stephen Chung; 06.08.2013