API компилятора typecript, проверка, getTypeCatalog? Есть ли таблица объявленных типов, доступная для проверки почему нет?

#typescript #typescript-compiler-api

#машинописный текст #typescript-compiler-api

Вопрос:

После инициализации API компилятора typescript следующим образом…

  const program = ts.createProgram(fileNames, options);
 const checker = program.getTypeChecker();
 

теперь программа скомпилирована, что означает, что программа typescript прошла всю программу один раз и получила возможность создать таблицу типов.

В отладочной версии typescript, доступной на github, есть функция проверки …

 ts.getTypeChecker().getTypeCatalog()
 

но в версии выпуска она недоступна.

Цитирую из ограниченной документации, которая описывает только на концептуальном уровне, без примеров:

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

Первое, что сделает средство проверки типов, — это объединить все символы из разных исходных файлов в единое представление и создать единую таблицу символов путем «слияния» любых общих символов (например, пространств имен, охватывающих несколько файлов).

После инициализации исходного состояния средство проверки типов готово ответить на любые вопросы о программе. Такие «вопросы» могут быть:

Какой символ для этого узла? Каков тип этого символа? Какие символы видны в этой части AST? Каковы доступные подписи для объявления функции? О каких ошибках следует сообщать для файла?

Средство проверки типов вычисляет все лениво; он только «разрешает» необходимую информацию для ответа на вопрос. Проверка будет проверять только узлы / символы / типы, которые вносят вклад в рассматриваемый вопрос, и не будет пытаться исследовать дополнительные объекты.

Итак, чтобы ответить на мой собственный вопрос: да и нет.

Да, потому что «TypeChecker … объединит все символы из разных исходных файлов в одно представление».

Нет, потому что «Средство проверки типов вычисляет все лениво; он только «разрешает» необходимую информацию для ответа на вопрос».

Доступно несколько десятков функций ts.getTypeChecker() — они недокументированы, и в примерах нет примеров использования для случая разрешения «глубоких» типов.

Я успешно использовал ts.getTypeChecker.forEachChild(...) для обхода файла и, например, поиска объявлений функций. Но с типом в руке я не знаю, как использовать средство проверки для изменения типа и создания иерархии вплоть до примитивов.

Комментарии:

1. Это где-нибудь в документах?

2. @Daniel_Knights — я расширил вопрос в ответ на ваш комментарий.

3. Я все еще не могу найти ни одной ссылки на getTypeCatalog .

4. Здесь говорится: «Имейте в виду, что это еще не стабильный API …».

Ответ №1:

Лучшее место для поиска этой информации — исходный код компилятора TypeScript.

getTypeCatalog Функция является внутренней и не является частью общедоступного API (исходного кода):

 interface TypeChecker {
  // ...omitted...

  /* @internal */ getTypeCatalog(): readonly Type[];

  // ...omitted...
}
 

Я не уверен, что доступ к ней настолько полезен.

Я успешно использовал ts.getTypeChecker.forEach(…) для обхода файла и, например, поиска объявлений функций. Но с типом в руке я не знаю, как использовать средство проверки для изменения типа и создания иерархии вплоть до примитивов.

Я не думаю forEach , что функция существует на TypeChecker (возможно, вы имели в виду forEach на символе?).

Для этого вы можете получить исходный файл ASTs ( program.getSourceFiles() ), просмотреть их с помощью sourceFile.forEachChild(child => { /* call child.forEachChild recursively */ }) , затем вы можете использовать typeChecker.getTypeAtLocation(child) для получения типов.

Комментарии:

1. Я изменился forEach на forEachChild . Очевидно, я бы не повторил дерево без использования forEachChild . getTypeAtLocation возвращает тип идентификатора, который не отвечает на мой вопрос. «Прочитать код» — да, но в любом случае это значение по умолчанию.

2. @CraigHicks forEachChild доступен для любого Node или экспортируемого ts модуля (не для TypeChecker). Извините, некоторые люди могут просматривать символы, а не AST, так что это не так очевидно … особенно при обсуждении forEach , который является символьным методом. Другими словами, я не верю, что это возможно получить через общедоступный API. Вероятно, вам лучше всего использовать объявления и использовать getTypeAtLocation (или, возможно, использовать getSymbolAtLocation и getSymbolsInScope в зависимости от вашей ситуации). Использование Type#getBaseTypes и Type#getProperties() может быть полезным.

3. getSymbolsInScope дает полезные результаты.