Como consumir módulos npm do typescript?

93

Estou tentando escrever. Funciona bem no cenário hello world. Agora estou tentando usar um módulo npm:

index.ts =

import _ = require('lodash')

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

Isso não funciona:

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

Olhar para a documentação do typescript e no google não ajudou. Outras questões S / O não foram respondidas ( aqui e aqui ) ou não estão relacionadas.

Elementos:

  • datilografado 1.8 mais recente
  • Sim, o lodash está instalado npm i --save lodashe existe em meu sistema de arquivos (verificado)
  • Eu também fiz typings i --save lodash
  • variantes import * as _ from 'lodash'ou const _ = require('lodash')também não funcionam
  • Tentei ajustar as opções de tsconfig.json conforme sugerido em outras respostas "moduleResolution": "node"e "module": "commonjs"conforme sugerido em algumas respostas, ainda não funciona

Como consumimos um pacote npm em typescript ??

Offirmo
fonte
2
Você adicionou a referência a lodash.d.ts em seu index.ts? Deve ser semelhante a este: ///<reference path="../typings/lodash/lodash.d.ts"/>
Granga
@Granga Funciona. Você pode adicionar isso como uma resposta?
Offirmo
2
Ainda bem que funciona. Blackus já adicionou a resposta e especifica o que sugeri ainda melhor. Porém, uma observação: quando os arquivos de entrada são especificados na linha de comando (que é o seu caso), os arquivos tsconfig.json são ignorados. ( fonte )
Granga

Respostas:

63

[EDIT] Muito obrigado por esta resposta! No entanto, em 2018, ele está desatualizado. Leitores, vejam as outras respostas.

Existem várias maneiras de importar módulos do npm. Mas se você não conseguir digitações, tscsempre reclamará que não consegue encontrar o módulo que você está solicitando (mesmo que o js transpilado esteja realmente funcionando).

  • Se você tiver digitações e não usar um tsconfig.json, use referencepara importar as digitações:

    /// <reference path="path/to/typings/typings.d.ts" />
    
    import * as _ from 'lodash`;
    
    console.log(_.toUpper('Hello, world !'))
    
  • Se você estiver usando um tsconfig.jsonarquivo, certifique-se de ter seu arquivo de digitação incluído (ou não excluído, sua escolha), e faça o importmesmo no exemplo anterior.

No caso em que não existam tipificações disponíveis. Você tem duas opções: gravar seu próprio .d.tsarquivo em um arquivo ou ignorar a verificação de tipo para a biblioteca.

Para ignorar completamente a verificação de tipo (esta não é a forma recomendada), importe a biblioteca em uma variável do tipo any.

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

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

tscvai reclamar que requirenão existe. Forneça nodedigitações ou declaredescartar o erro.

Blackus
fonte
2
Resposta completa com 3 soluções. +1
Offirmo
1
Adição: funciona até mesmo ts-nodecontanto que o índice de tsconfig.json
digitação
Estou confuso com o que você quer dizer com "declarar para descartar o erro". Preciso fazer essa alteração no módulo que estou tentando importar?
Slug
1
Esta resposta está seriamente desatualizada. Veja minha nova resposta abaixo stackoverflow.com/a/53786892/587407
Offirmo
53

[2018/12] Nova resposta atualizada a esta pergunta que fiz em 2016, que ainda mostra muita atividade apesar de ter respostas desatualizadas.

Para encurtar a história, o TypeScript requer informações de tipo sobre o código do seu pacote (também conhecido como " arquivos de declaração de tipo " ou "tipificações") e, com razão, diz a você que, de outra forma, você estaria perdendo todo o sentido do TypeScript. Existem várias soluções para fornecê-los ou optar por não recebê-los, listados aqui em ordem de prática recomendada:


Solução 0 : o módulo já fornece as digitações. Se seu package.json contiver uma linha como esta:

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

já está habilitado para TypeScript. Provavelmente não é o caso se você estiver lendo esta página, então vamos continuar ...


Solução 1 : use tipificações fornecidas pela comunidade do DefinitelyTyped . Para um módulo "foo", tente o seguinte:

npm add -D @types/foo

se funcionar, jackpot! Agora você tem as digitações e pode usar seu módulo. Se o npm reclamar que não consegue encontrar o módulo @ types / foo, vamos continuar ...


Solução 2 : forneça tipificações personalizadas sobre este módulo. (com a opção de fazer esforço zero)

  1. Crie uma pasta chamada "typings-custom" na raiz do seu projeto
  2. Consulte o conteúdo desta pasta em seu tsconfig.json:
"include": [
    "./typings-custom/**/*.ts"
]
  1. Crie um arquivo com este nome exato: foo.d.ts [foo = nome do módulo] com o conteúdo:
declare module 'foo'

Seu código TypeScript agora deve compilar, embora sem nenhuma informação de tipo (TypeScript considere o módulo foo do tipo "qualquer").

Você também pode tentar escrever as informações de tipo por conta própria, olhando o documento oficial e / ou exemplos do DefinitelyTyped . Se você fizer isso, pense em contribuir com suas digitações diretamente no módulo (solução 0, se o autor do módulo aceitar) ou em DefinitelyTyped (solução 1)

Offirmo
fonte
1
@Offirmo, também podemos declarar várias tipificações personalizadas em um único arquivo! Portanto, não há necessidade de vários arquivos (talvez?).
lazycipher
A etapa 2. Reference the content of this folder in your tsconfig.json:dá o seguinte erro: Unknown compiler option 'include'.
Sumit
1
@Sumit não é uma opção de compilador, deve ser um irmão decompilerOptions
Offirmo
24

Você provavelmente está perdendo os arquivos de declaração .

Consulte DefinitelyTyped para obter mais informações.


Experimente isto:

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

Agora você pode importar.

import _ from 'lodash';

Se o módulo que você está importando tiver várias exportações , você pode fazer isso:

import { Express, Router } from 'express';

Se o módulo que você está importando "não tem exportação padrão", você precisa fazer o seguinte:

import * as http from 'http';
Derek Soike
fonte
Por que temos que usar * as _e não apenas _ from 'lodash'como no código ES6?
JohnnyQ de
@JohnnyQ Bom argumento. Usar import _ from 'lodash';é melhor neste caso. Atualizei minha resposta para mostrar diferentes maneiras de importar e por que você os usaria.
Derek Soike
1
O * as _ é necessário se o módulo não tiver exportação padrão. O compilador tsc avisará sobre isso.
user2867342
Por 'nenhuma exportação padrão' significa que nenhum tipo de texto definido (ou seja, importar um módulo JavaScript simples)? Sou novo em JS / Typescript ....
Big Rich
2
@BigRich "Sem exportação padrão" significa que o módulo não tem uma export default <...>instrução. Dê uma olhada na seção "Exportações padrão" da Documentação dos Módulos de Texto Tipo .
Derek Soike
5

Funcionou para mim

  1. Crie uma pasta chamada "typings".
  2. Na pasta de digitação , crie um nome de arquivo module-name.d.ts . Contém:

    declare module "module-name";

  3. Em tsconfig.json, consulte a pasta

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

Quynh Ngo
fonte
Oi! Obrigado por contribuir. Este método já está incluído na minha resposta e deve ser usado apenas como último recurso.
Offirmo 01 de
A etapa 3 In tsconfig.json, refer to the folderUnknown compiler option 'typesRoots'.
:,
1
@Sumit no meu caso, "typesRoots" está dentro de "compilerOptions"
Quynh Ngo
1
É typeRoots, não typesRoots, e deve estar dentro de compilerOptions
CM
0

Tenho recebido este erro e nenhuma das respostas funcionou para mim, mas descobri algo quando você deseja trabalhar com o módulo de nó no script de digitação, instale-os como

$npm install @types/<module_name>

por exemplo

npm install @types/cheerio

ao invés de dizer

npm install cheerio
Crispen Gari
fonte