Ответ 1
К сожалению, эти вещи в настоящее время не очень хорошо документированы, но даже если вы смогли заставить их работать, отпустите свою конфигурацию, чтобы вы понимали, что делает каждая часть, и как она связана с тем, как процессы и нагрузки typescript типизации.
Сначала отпустите полученную ошибку:
error TS2688: Cannot find type definition file for 'lodash'.
Эта ошибка на самом деле не связана с вашими импортами или ссылками или вашей попыткой использовать lodash в любом месте ваших ts файлов. Скорее, это происходит из-за непонимания того, как использовать свойства typeRoots
и types
, поэтому давайте немного подробнее о них.
Дело в свойствах typeRoots:[]
и types:[]
заключается в том, что они являются НЕ универсальными способами загрузки файлов с произвольным объявлением (*.d.ts
).
Эти два свойства напрямую связаны с новой функцией TS 2.0, которая позволяет упаковывать и загружать объявления ввода из пакетов NPM.
Это очень важно понять, что они работают только с папками в формате NPM (т.е. папке, содержащей package.json или index.d.ts).
По умолчанию для typeRoots
:
{
"typeRoots" : ["node_modules/@types"]
}
По умолчанию это означает, что typescript перейдет в папку node_modules/@types
и попытается загрузить каждую подпапку, найденную там как пакет npm.
Важно понимать, что это не удастся, если папка не имеет структуры, похожей на npm.
Это то, что происходит в вашем случае, и источник вашей первоначальной ошибки.
Вы переключили typeRoot следующим образом:
{
"typeRoots" : ["./typings"]
}
Это означает, что typescript теперь сканирует папку ./typings
для вложенных папок и пытается загрузить каждую подпапку, которую он находит в качестве модуля npm.
Итак, давайте притвориться, что вы только что установили typeRoots
, чтобы указать на ./typings
, но еще не имели настройки свойств types:[]
. Вероятно, вы увидите эти ошибки:
error TS2688: Cannot find type definition file for 'custom'.
error TS2688: Cannot find type definition file for 'global'.
Это потому, что tsc
сканирует вашу папку ./typings
и находит подпапки custom
и global
. Затем он пытается интерпретировать их как типизацию типа пакета npm, но в этих папках нет index.d.ts
или package.json
, поэтому вы получаете ошибку.
Теперь поговорим немного о свойстве types: ['lodash']
, которое вы задаете. Что это делает? По умолчанию typescript загрузит подпапки все, найденные в вашем typeRoots
. Если вы укажете свойство types:
, оно будет загружать только эти определенные подпапки.
В вашем случае вы сообщаете ему, чтобы загрузить папку ./typings/lodash
, но она не существует. Вот почему вы получаете:
error TS2688: Cannot find type definition file for 'lodash'
Итак, давайте обобщим то, что мы узнали. typescript 2.0 ввел typeRoots
и types
для загрузки файлов декларации, упакованных в пакеты npm. Если у вас есть настраиваемые типизации или отдельные свободные файлы d.ts
, которые не содержатся в папке, следующей за пакетами пакетов npm, эти два новых свойства не являются тем, что вы хотите использовать. typescript 2.0 действительно не изменяет, как они будут потребляться. Вам просто нужно включить эти файлы в свой контекст компиляции одним из многих стандартных способов:
-
Непосредственно включив его в файл
.ts
:///<reference path="../typings/custom/lodash.d.ts" />
-
Включение
./typings/custom/lodash.d.ts
в ваше свойствоfiles: []
. -
Включение
./typings/index.d.ts
в ваше свойствоfiles: []
(которое затем рекурсивно включает в себя другие типы. -
Добавление
./typings/**
в вашincludes:
Надеемся, что на основе этой дискуссии вы сможете узнать, почему изменения, которые вы с ума со своим tsconfig.json
, снова заработали.
EDIT:
Одна вещь, о которой я забыл упомянуть, заключается в том, что свойства typeRoots
и types
действительно полезны только для загрузки автоматической глобальных деклараций.
Например, если вы
npm install @types/jquery
И вы используете tsconfig по умолчанию, тогда этот пакет типов jquery будет загружен автоматически, и $
будет доступен по всем вашим скриптам, не имея необходимости делать дальнейшие ///<reference/>
или import
Свойство typeRoots:[]
предназначено для добавления дополнительных мест, откуда автоматически загружаются пакеты типов.
Основной прецедент использования types:[]
- это отключить автоматическое поведение загрузки (путем установки его в пустой массив), а затем только перечисление конкретных типов, которые вы хотите включить глобально.
Другим способом загрузки пакетов типов из различных typeRoots
является использование новой директивы ///<reference types="jquery" />
. Обратите внимание на types
вместо path
. Опять же, это полезно только для файлов глобальной декларации, обычно для тех, которые не выполняют import/export
.
Теперь вот одна из вещей, которая вызывает путаницу с typeRoots
. Помните, я сказал, что typeRoots
- это глобальное включение модулей. Но @types/folder
также участвует в стандартном модульном разрешении (независимо от вашей настройки typeRoots
).
В частности, явно импортирование модулей всегда обходит все опции includes
, excludes
, files
, typeRoots
и types
. Поэтому, когда вы делаете:
import {MyType} from 'my-module';
Все вышеупомянутые свойства полностью игнорируются. Соответствующие свойства при разрешении модуля: baseUrl
, paths
и moduleResolution
.
В принципе, при использовании разрешения модуля node
он начнет поиск имени файла my-module.ts
, my-module.tsx
, my-module.d.ts
, начиная с папки, на которую указывает ваша конфигурация baseUrl
.
Если он не найдет файл, он будет искать папку с именем my-module
и затем выполнить поиск package.json
с помощью свойства typings
, если есть свойство package.json
или no typings
внутри которого указывается, какой файл для загрузки он будет искать index.ts/tsx/d.ts
в этой папке.
Если это все еще не удастся, он будет искать эти же вещи в папке node_modules
, начиная с вашего baseUrl/node_modules
.
Кроме того, если он не найдет их, он будет искать baseUrl/node_modules/@types
для всех тех же вещей.
Если он все равно ничего не найдет, он начнет переходить в родительский каталог и будет искать node_modules
и node_modules/@types
там. Он будет продолжать подниматься по каталогам, пока не достигнет корня вашей файловой системы (даже получив node -модули вне вашего проекта).
Одна вещь, которую я хочу подчеркнуть, заключается в том, что разрешение модуля полностью игнорирует любой установленный typeRoots
. Поэтому, если вы настроили typeRoots: ["./my-types"]
, это не будет проверяться при явном разрешении модуля. Он служит только в качестве папки, в которую вы можете поместить файлы глобального определения, которые хотите сделать доступными для всего приложения, без дополнительной необходимости импорта или ссылки.
Наконец, вы можете переопределить поведение модуля с помощью сопоставлений пути (т.е. свойство paths
). Так, например, я упомянул, что при попытке разрешить модуль не запрашивается какой-либо пользовательский typeRoots
. Но если вам нравится, вы можете сделать это так:
"paths" :{
"*": ["my-custom-types/*", "*"]
}
Что это делает для всех импортных товаров, которые соответствуют левой части, попробуйте изменить импорт, как в правой части, перед тем как попытаться включить его (*
в правой части представляет вашу начальную строку импорта. если вы импортируете:
import {MyType} from 'my-types';
Сначала попробуйте импорт, как если бы вы написали:
import {MyType} from 'my-custom-types/my-types'
И тогда, если он не нашел, он попытается снова с префиксом (второй элемент в массиве - это просто *
, что означает начальный импорт.
Таким образом, вы можете добавить дополнительные папки для поиска пользовательских файлов декларации или даже настраиваемых модулей .ts
, которые вы хотите иметь import
.
Вы также можете создавать настраиваемые сопоставления для определенных модулей:
"paths" :{
"*": ["my-types", "some/custom/folder/location/my-awesome-types-file"]
}
Это позволит вам сделать
import {MyType} from 'my-types';
Но затем прочитайте эти типы из some/custom/folder/location/my-awesome-types-file.d.ts