TypeScript 1.5, отражение и декоратор

Мне было интересно, можно ли использовать отражение и, в частности, отражение класса в отношении декоратора, свойства, параметра или метода?

Можно ли использовать отражатель для получения информации, используемой в декораторах?

Если это возможно, то как мы можем это сделать? Иначе почему мы не можем этого сделать?

РЕДАКТИРОВАТЬ :

У меня есть приложение, в котором я использую декораторы для вставки данных из serviceRegistry в декоратор под названием @Inject.

В этом приложении я вручную заполняю простой реестр сервисов, например:

serviceRegistry.push(MyClass1)
serviceRegistry.push(MyClass2)
...
serviceRegistry.push(MyClass100)

Цель состоит в том, чтобы иметь возможность заполнить этот реестр служб классами, украшенными аннотацией @ToInject, во время выполнения.

Это позволит мне не заполнять этот реестр вручную, а просто автоматизировать это.

Спасибо за заранее


person mfrachet    schedule 05.06.2015    source источник
comment
Здесь это пример. Мне не удалось заставить его работать с PhantomJS 2, который только что сообщил о синтаксической ошибке.   -  person Stefan Hanke    schedule 05.06.2015
comment
Какова ваша конечная цель? Если бы вы могли привести пример, это помогло бы ответить на ваш вопрос.   -  person zlumer    schedule 05.06.2015


Ответы (2)


Вы можете использовать отражение, импортировав пакет reflect-metadata.

import 'reflect-metadata';

Используйте его с TypeScript 1.5 и флагом компилятора emitDecoratorMetadata, установленным в true. Не забудьте также включить ссылку на reflect-metadata.d.ts.

Вам нужно реализовать свои собственные декораторы:

// declare property decorator
function logType(target : any, key : string) {
  var t = Reflect.getMetadata("design:type", target, key);
  console.log(`${key} type: ${t.name}`);
}

class Demo{ 
  @logType // apply property decorator
  public attr1 : string;
}

Он войдет в консоль:

attr1 type: String

Другой пример:

// declare parameter decorator
function logParamTypes(target : any, key : string) {
  var types = Reflect.getMetadata("design:paramtypes", target, key);
  var s = types.map(a => a.name).join();
  console.log(`${key} param types: ${s}`);
}  

class Foo {}
interface IFoo {}

class Demo{ 
  @logParameters // apply parameter decorator
  doSomething(
    param1 : string,
    param2 : number,
    param3 : Foo,
    param4 : { test : string },
    param5 : IFoo,
    param6 : Function,
    param7 : (a : number) => void,
  ) : number { 
      return 1
  }
}

Он войдет в консоль:

doSomething param types: String, Number, Foo, Object, Object, Function, Function

Обратите внимание, что интерфейсы IFoo и объектный литерал { test : string} сериализуются как Object. Правила сериализации:

  • number сериализовано как Number
  • string серийный номер String
  • boolean серийный номер Boolean
  • any серийный номер Object
  • void сериализуется как undefined
  • Array серийный номер Array
  • Если Tuple, серийный номер Array
  • Если class сериализует его как конструктор класса
  • Если Enum сериализует его как Number
  • Если есть хотя бы один позывной, сериализованный как Function
  • В противном случае сериализуется как Object (включая интерфейсы)

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

Вы также можете получить возвращаемый тип функции, используя:

Reflect.getMetadata("design:returntype", target, key);

Если вам нужна дополнительная информация о декораторах, вы можете прочитать: Декораторы и отражение метаданных в TypeScript: от новичка до эксперта

person Remo H. Jansen    schedule 27.08.2015
comment
Не могли бы вы уточнить, не забудьте также включить ссылку на Reflect-metadata.d.ts? - person Learner; 07.12.2016
comment
Метаданные Reflect включают файлы .d.ts в модуле npm. Когда я писал этот ответ, требовалось использовать /// <reference path=""> для файла dts. Сегодня, если вы используете TS ›= 2.0, вам не нужно этого делать. - person Remo H. Jansen; 07.12.2016
comment
Вот еще один пример использования декораторов stackoverflow.com/questions/38085883/ - person Chris Jaga; 19.03.2017

Я только что выпустил расширенную версию компилятора TypeScript, которая обеспечивает полные возможности отражения:

  • Метаданные классов/интерфейсов во время выполнения
  • Создание экземпляров классов из объектов метаданных
  • Получить метаданные из конструкторов классов

Вы можете проверить это здесь

person pcan    schedule 15.08.2016
comment
Могу я попросить вас просмотреть как предлагать персональные библиотеки с открытым исходным кодом? - person Martijn Pieters; 16.08.2016
comment
Сообщество TypeScript уже давно требует возможности отражения. Это ответ на вопрос. Ни одна другая версия библиотеки/компилятора не может справиться с этими требованиями. Посмотри на это. Кроме того, я сказал, что только что выпустил... так что ясно, что это мой проект. - person pcan; 16.08.2016
comment
Я имел в виду, что вы не должны копировать один и тот же ответ без подробностей на каждый вопрос о TypeScript здесь, не адаптируя свой ответ и не включая правильные примеры. - person Martijn Pieters; 16.08.2016