К сожалению, эти вещи в настоящее время не очень хорошо документированы, но даже если вы смогли заставить его работать, давайте рассмотрим вашу конфигурацию, чтобы вы поняли, что делает каждая часть и как она связана с тем, как машинописный текст обрабатывает и загружает типизацию.
Сначала рассмотрим ошибку, которую вы получаете:
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"]
}
По умолчанию это означает, что машинописный текст войдет в node_modules/@types
папку и попытается загрузить каждую подпапку, которую он там найдет, как пакет npm .
Важно понимать, что это не удастся, если папка не имеет структуры, подобной пакету npm.
Это то, что происходит в вашем случае, и источник вашей первоначальной ошибки.
Вы переключили typeRoot на:
{
"typeRoots" : ["./typings"]
}
Это означает, что машинописный текст теперь будет сканировать ./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']
вами свойстве. Что это значит? По умолчанию машинописный текст загружает все подпапки, которые он находит в вашем 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
дела, снова работают.
РЕДАКТИРОВАТЬ:
Одна вещь, о которой я забыл упомянуть, это то, что 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
или нет 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
paths
и чем он отличается отinclude
типирования?