File Module Details
Шаблон зовнішнього модуля TypeScript містить велику потужність і зручність використання. Тут ми обговорюємо його потужність і деякі моделі, необхідні для відображення використання в реальному світі.
Clarification: commonjs, amd, es modules, others
Спочатку нам потрібно прояснити (жахливу) невідповідність систем модулів. Я просто дам вам свою поточну рекомендацію та видалю шум, тобто не покажу всі інші способи роботи.
З того самого TypeScript ви можете генерувати різний JavaScript залежно від параметра module. Ось речі, які ви можете ігнорувати (мені не цікаво пояснювати мертві технології):
AMD: не використовувати. Був лише браузер.
SystemJS: це був хороший експеримент. Замінено модулями ES.
Модулі ES: ще не готові.
Тепер це лише варіанти для генерування JavaScript. Замість цих параметрів використовуйте module:commonjs
Те, як ви пишете модулі TypeScript, також є дещо безладним. Ось як цього не робити сьогодні:
import foo = require('foo'). тобтоimport/require. Натомість використовуйте синтаксис модуля ES.
Круто, покінчивши з цим, давайте розглянемо синтаксис модуля ES.
Резюме: Використовуйте
module:commonjsі використовуйте синтаксис модуля ES для імпорту/експорту/авторських модулів.
ES Module syntax
Експортувати змінну (або тип) так само просто, як додати префікс ключового слова
export.
// file `foo.ts`
export let someVar = 123;
export type SomeType = {
foo: string;
};Експортування змінної або типу в спеціальному операторі
export.
Експортування змінної або типу в спеціальному операторі
exportз перейменуванням.
Імпорт змінну або тип за допомогою
import.
Імпортуйте змінну або тип за допомогою
importз перейменуванням.
Імпортуйте все з модуля в назву за допомогою
import * as, наприклад.
Імпортуйте файл тільки для його побічного ефекту за допомогою одного оператора імпорту:
Повторний експорт усіх елементів з іншого модуля
Повторний експорт лише деяких елементів з іншого модуля
Повторний експорт лише деяких елементів з іншого модуля * з перейменуванням *
Default exports/imports
Як ви дізнаєтесь пізніше, я не прихильник експорту за замовчуванням. Тим не менш, тут є синтаксис для експорту та використання стандартних експортів
Експортуйте за допомогою
export defaultперед змінною (не потрібно
let / const / var)перед функцією
перед уроком
Імпортуйте за допомогою синтаксису
import someName from "someModule"(ви можете назвати імпорт як завгодно).
Module paths
Я просто припускаю
moduleResolution: "Node". Це параметр, який ви повинні мати у своїй конфігурації TypeScript. Цей параметр автоматично передбачаєтьсяmodule:commonjs.
Є два різних типи модулів. Розрізнення визначається розділом шляху оператора імпорту (наприклад, import foo from 'THIS IS THE PATH SECTION').
Модулі відносного шляху (де шлях починається з
., наприклад./someFileабо../../someFolder/someFileтощо)Інші модулі динамічного пошуку (наприклад,
'core-js'або'typestyle'або'react'або навіть'react/core'тощо)
Основна відмінність полягає в тому, як модуль вирішується у файловій системі.
Я буду використовувати концептуальний термін місце, який я поясню після згадки шаблону пошуку.
Relative path modules
Легко, просто дотримуйтеся відносного шляху :)
якщо файл bar.ts виконує імпорт * як foo з './foo';, тоді місце foo має існувати в тій же папці.
якщо файл
bar.tsвиконуєімпорт * як foo з '../foo';, тоді місцеfooмає існувати в папці вище.якщо файл
bar.tsвиконуєімпорт * як foo з '../someFolder/foo';, тоді на одну папку вище, має бути папкаsomeFolderз місцемfoo
Або будь-який інший відносний шлях, який ви можете придумати :)
Dynamic lookup
Якщо шлях імпорту не відносний, пошук керується роздільністю стилю вузла. Тут я наведу лише простий приклад:
У вас є
імпорт * як foo з 'foo', нижче наведено місця, які перевіряються по порядку./node_modules/foo../node_modules/foo../../node_modules/fooДо кореня файлової системи
У вас є
імпорт * як foo з 'something/foo', нижче наведено місця, які перевіряються по порядку./node_modules/something/foo../node_modules/something/foo../../node_modules/something/fooДо кореня файлової системи
What is place
Коли я кажу місця, які перевіряються, я маю на увазі, що в цьому місці перевіряються такі речі. Наприклад. для місця foo:
Якщо місцем є файл, напр.
foo.ts, ура!інакше, якщо місцем є папка і є файл
foo/index.ts, ура!інакше, якщо місцем є папка і існує
foo/package.jsonі файл, указаний у ключіtypesу package.json, тоді ура!інакше, якщо місцем є папка, і існує
package.jsonі файл, указаний у ключіmainу package.json, який існує, тоді ура!
Під файлом я насправді маю на увазі .ts / .d.ts і .js.
І це все. Тепер ви експерт із пошуку модулів (це не маленький подвиг!).
Overturning dynamic lookup just for types
Ви можете оголосити модуль глобально для свого проекту за допомогою declare module 'somePath', а потім імпорт буде чарівним чином вирішувати цей шлях
e.g.
and then:
import/require for importing type only
import/require for importing type onlyНаступна заява:
насправді робить дві речі:
Імпортує інформацію про тип модуля foo.
Визначає залежність часу виконання від модуля foo.
Ви можете вибирати так, щоб завантажувалася лише інформація про тип і не виникала залежність під час виконання. Перш ніж продовжити, можливо, ви захочете підсумувати розділ просторів для оголошень у книзі.
Якщо ви не використовуєте імпортоване ім’я в просторі оголошення змінних, імпорт буде повністю видалено зі згенерованого JavaScript. Це найкраще пояснити на прикладах. Як тільки ви це зрозумієте, ми представимо вам випадки використання.
Example 1
створить JavaScript:
Це вірно. Порожній файл як foo не використовується.
Example 2
створить JavaScript:
Це тому, що foo (або будь-яка з його властивостей, наприклад foo.bas) ніколи не використовується як змінна.
Example 3
створить JavaScript (припускаючи, що commonjs):
Це тому, що foo використовується як змінна.
Use case: Lazy loading
Висновок типу потрібно зробити заздалегідь. Це означає, що якщо ви хочете використовувати певний тип із файлу foo у файлі bar, вам доведеться зробити:
Однак ви можете завантажувати файл foo лише під час виконання за певних умов. У таких випадках вам слід використовувати імпортовану назву лише в анотаціях типу, а не як змінну. Це видаляє будь-який попередній код залежності часу виконання, який впроваджується TypeScript. Потім вручну імпортуйте фактичний модуль, використовуючи код, який відповідає вашому завантажувачу модулів.
Як приклад, розглянемо наступний код на основі commonjs, де ми завантажуємо модуль `'foo`` лише під час певного виклику функції:
Схожий приклад на amd (using requirejs) буде:
Цей шаблон зазвичай використовується:
у веб-додатках, де ви завантажуєте певний JavaScript за певними маршрутами,
у вузлових програмах, де ви завантажуєте лише певні модулі, якщо це необхідно для прискорення завантаження програми.
Use case: Breaking Circular dependencies
Подібно до випадку використання відкладеного завантаження, деякі завантажувачі модулів (commonjs/node і amd/requirejs) погано працюють із циклічними залежностями. У таких випадках корисно мати ліниве завантаження коду в одному напрямку та завантаження модулів наперед в іншому напрямку.
Use case: Ensure Import
Іноді ви хочете завантажити файл лише для побічного ефекту (наприклад, модуль може зареєструватися в якійсь бібліотеці, наприклад CodeMirror addons тощо). Однак, якщо ви просто виконуєте команду import/require, транспільований JavaScript не міститиме залежності від модуля, і ваш завантажувач модуля (наприклад, веб-пакет) може повністю ігнорувати імпорт. У таких випадках ви можете використовувати змінну ensureImport, щоб переконатися, що скомпільований JavaScript приймає залежність від модуля, наприклад:
Last updated