На жаль, в даний час ці речі не дуже добре задокументовані, але навіть якщо ви змогли змусити його працювати, давайте переглянемо вашу конфігурацію, щоб ви зрозуміли, що робить кожна частина і як це пов’язано з тим, як машинопис обробляє та завантажує типізації.
Спочатку розглянемо помилку, яку ви отримуєте:
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']
властивість, яку ви встановлюєте. Що це робить? За замовчуванням typecript завантажує всі вкладені папки, знайдені у вашому 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:[]
Властивість призначене , щоб додати додаткові місця , звідки типу пакети будуть завантажені frrom автоматично.
В 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
там. Він буде продовжувати рухатися вгору по каталогах, доки не досягне кореня вашої файлової системи (навіть отримуючи вузлові модулі поза вашим проектом).
Одне, на чому я хочу наголосити, - це те, що роздільна здатність модуля повністю ігнорує будь- 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
для набору тексту?