Як споживати модулі npm з машинопису?


90

Я роблю постріл на машинописі. Це чудово працює на світовій арені. Зараз я намагаюся використовувати модуль npm:

index.ts =

import _ = require('lodash')

console.log(_.toUpper('Hello, world !'))

Це не працює:

  • tsc index.ts -> Cannot find module 'lodash'. (2307)
  • node-ts index.js -> Cannot find module 'lodash'. (2307)

Перегляд документації машинопису та в Google не допомогло. Інші питання S / O не відповідають ( тут і тут ) або не пов’язані.

Елементи:

  • машинопис 1.8 остання
  • Так, lodash встановлено npm i --save lodashта існує у моїй файловій системі (позначено)
  • Я теж зробив typings i --save lodash
  • варіанти import * as _ from 'lodash'або const _ = require('lodash')також не працюють
  • Я спробував налаштувати параметри tsconfig.json, як пропонується в інших відповідях "moduleResolution": "node"і "module": "commonjs"як пропонується в деяких відповідях, все ще не працює

Як ми споживаємо пакет npm у машинописі ??


2
Ви додали посилання на lodash.d.ts у своєму index.ts? Це повинно виглядати приблизно так: ///<reference path="../typings/lodash/lodash.d.ts"/>
Гранга

@Granga Це працює. Чи можете ви додати це як відповідь?
Offirmo

2
Радий, що це працює. Блекус вже додав відповідь, і в ній ще краще вказується те, що я запропонував. Хоча одна примітка: коли в командному рядку вказано вхідні файли (що є вашим випадком), файли tsconfig.json ігноруються. ( джерело )
Granga

Відповіді:


61

[EDIT] Велике спасибі за цю відповідь! Однак станом на 2018 рік він застарів. Читачі, погляньте на інші відповіді.

Існує кілька способів імпорту модулів з npm. Але якщо ви не отримуєте типізацій, tscзавжди будете скаржитися, що він не може знайти потрібний вам модуль (навіть якщо переписаний js насправді працює).

  • Якщо у вас є набори тексту і ви не використовуєте a tsconfig.json, скористайтесь referenceімпортом набору тексту:

    /// <reference path="path/to/typings/typings.d.ts" />
    
    import * as _ from 'lodash`;
    
    console.log(_.toUpper('Hello, world !'))
    
  • Якщо ви використовуєте tsconfig.jsonфайл, обов’язково включіть файл типізації (або не виключайте, на ваш вибір) і зробіть importподібне на попередньому прикладі.

У тому випадку, коли немає доступних типізацій. У вас є два варіанти: написати власний .d.tsфайл або ігнорувати перевірку типу для бібліотеки.

Щоб повністю ігнорувати перевірку типу (це не рекомендований спосіб), імпортуйте бібліотеку до змінної типу any.

 const _: any = require('lodash');

 console.log(_.toUpper('Hello, world !'))

tscбуде скаржитися, що requireне існує. Надайте nodeтипізацію або declareїї, щоб відхилити помилку.


2
Повна відповідь із 3 рішеннями. +1
Офірмо

Додаток: він навіть працює з тим часом ts-node, доки на індекс типізації посилаєтьсяtsconfig.json
Offirmo

Мене бентежить те, що ви маєте на увазі "оголосити це, щоб відкинути помилку". Чи потрібно мені вносити ці зміни в модуль, який я намагаюся імпортувати?
Slug

1
Ця відповідь сильно застаріла. Дивіться мій новий відповідь нижче stackoverflow.com/a/53786892/587407
Offirmo

50

[2018/12] Нова, сучасна відповідь на це запитання, яке я задав у 2016 році, яке все ще демонструє багато активності, незважаючи на застарілі відповіді.

Коротше кажучи, TypeScript вимагає інформації про тип коду вашого пакета (він же " файли декларації типу ", він же "типізація") і по праву повідомляє вам, що в іншому випадку ви втратили б цілий сенс TypeScript. Існує кілька рішень щодо їх надання або відмови від них, перелічених тут у порядку найкращої практики:


Рішення 0 : модуль уже забезпечує типізацію. Якщо пакет package.json містить такий рядок:

"typings": "dist/index.d.ts",

це вже включено TypeScript. Швидше за все, це не так, якщо ви читаєте цю сторінку, тож продовжимо ...


Рішення 1. Використовуйте введені спільнотою типи з DefinitelyTyped . Для модуля "foo" спробуйте:

npm add -D @types/foo

якщо це працює, джек-пот! Тепер ви маєте набір тексту і можете використовувати свій модуль. Якщо npm скаржиться, що не може знайти модуль @ types / foo, продовжимо ...


Рішення 2 : надайте власні типи тексту для цього модуля. (з можливістю робити нульові зусилля)

  1. Створіть папку з назвою "typings-custom" у корені вашого проекту
  2. Посилання на вміст цієї папки у вашому tsconfig.json:
"include": [
    "./typings-custom/**/*.ts"
]
  1. Створіть файл із точною назвою: foo.d.ts [foo = назва модуля] із вмістом:
declare module 'foo'

Тепер ваш код TypeScript повинен компілюватися, хоча і не містить інформації про тип (TypeScript розглядає модуль foo типу "будь-який").

Ви також можете спробувати написати інформацію про тип самостійно, переглянувши офіційний документ та / або приклади з DefinitelyTyped . Якщо ви це зробите, подумайте надсилати свої типізації або безпосередньо в модуль (рішення 0, якщо автор модуля приймає) або в DefinitelyTyped (рішення 1)


1
@Offirmo, ми також можемо оголосити кілька власних типізацій в одному файлі! Отже, немає необхідності в декількох файлах (можливо?).
леніцифер

Крок 2. Reference the content of this folder in your tsconfig.json:дає наступне повідомлення про помилку: Unknown compiler option 'include'.
SUMIT

1
@Sumit, це не варіант компілятора, це повинен бути рідний братcompilerOptions
Offirmo

22

Ймовірно, вам бракує файлів декларацій .

Див DefinitelyTyped для отримання додаткової інформації.


Спробуйте це:

npm install --save lodash
npm install --save @types/lodash

Тепер ви можете імпортувати.

import _ from 'lodash';

Якщо модуль, який ви імпортуєте, має кілька експортів , ви можете зробити це:

import { Express, Router } from 'express';

Якщо модуль, який ви імпортуєте, "не має експорту за замовчуванням", вам потрібно зробити це:

import * as http from 'http';

Чому ми повинні використовувати, * as _а не так, _ from 'lodash'як у коді ES6?
JohnnyQ

@JohnnyQ Гарна думка. import _ from 'lodash';У цьому випадку використовувати краще. Я оновив свою відповідь, щоб показати різні способи імпорту та чому ви їх використовуєте.
Дерек Сойке

1
Це * as _ потрібно, якщо модуль не має експорту за замовчуванням. Про це попередить компілятор tsc.
користувач2867342

Під "відсутністю експорту за замовчуванням" це означає, що не визначено типів Typescript (тобто імпорт простого модуля JavaScript)? Я новачок у JS / Typescript ....
Big Rich

2
@BigRich "Немає експорту за замовчуванням" означає, що модуль не має export default <...>оператора. Погляньте на розділ "Експорт за замовчуванням" Документації до модулів машинопису .
Дерек Сойке,

4

У мене це спрацювало.

  1. Створіть папку з назвою "typing".
  2. У папці типів створіть ім'я файлу module-name.d.ts . Це містить:

    declare module "module-name";

  3. У tsconfig.json зверніться до папки

    "typeRoots": [ "./typings", "../node_modules/@types" ]


Привіт! Дякуємо за внесок. Цей метод уже включений у мою відповідь і повинен застосовуватися лише в крайньому випадку.
Offirmo,

Крок 3: In tsconfig.json, refer to the folderдає наступне повідомлення про помилку:Unknown compiler option 'typesRoots'.
SUMIT

1
@Sumit у моєму випадку, "typesRoots" знаходиться всередині "compilerOptions"
Quynh Ngo

1
Це typeRoots, а не typeRoots, і він повинен бути всередині compilerOptions
CM,

0

Я отримував цю помилку, і жодна з відповідей не працювала для мене, але я щось з’ясовую, коли ви хочете працювати з модулем вузла в TypeScript, встановлюйте їх як

$npm install @types/<module_name>

наприклад

npm install @types/cheerio

замість сказати

npm install cheerio
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.