¿Cómo consumir módulos npm de mecanografiado?

91

Estoy intentando escribir a máquina. Funciona bien en el escenario de hola mundo. Ahora estoy tratando de usar un módulo npm:

index.ts =

import _ = require('lodash')

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

Esto no funciona:

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

Mirar la documentación mecanografiada y en Google no ayudó. Otras preguntas de S / O están sin respuesta ( aquí y aquí ) o no están relacionadas.

Elementos:

  • mecanografiado 1.8 último
  • Sí, lodash está instalado npm i --save lodashy existe en mi sistema de archivos (marcado)
  • Yo tambien lo hice typings i --save lodash
  • variantes import * as _ from 'lodash'o const _ = require('lodash')tampoco funcionan
  • Intenté ajustar las opciones de tsconfig.json como se sugiere en otras respuestas "moduleResolution": "node"y "module": "commonjs"como se sugiere en algunas respuestas, todavía no funciona

¿Cómo consumimos un paquete npm en mecanografiado?

Offirmo
fuente
2
¿Agregó una referencia a lodash.d.ts en su index.ts? Debería verse similar a esto: ///<reference path="../typings/lodash/lodash.d.ts"/>
Granga
@Granga Funciona. ¿Puedes agregar esto como respuesta?
Offirmo
2
Me alegro de que funcione. Blackus ya ha agregado la respuesta y especifica lo que sugerí aún mejor. Sin embargo, una nota: cuando los archivos de entrada se especifican en la línea de comando (que es su caso), los archivos tsconfig.json se ignoran. ( fuente )
Granga

Respuestas:

61

[EDITAR] ¡Muchas gracias por esta respuesta! Sin embargo, a partir de 2018, está desactualizado. Lectores, echen un vistazo a las otras respuestas.

Hay varias formas de importar módulos desde npm. Pero si no obtiene mecanografía, tscsiempre se quejará de que no puede encontrar el módulo que necesita (incluso si js transpilado realmente funciona).

  • Si tiene mecanografía y no usa a tsconfig.json, utilice referencepara importar las mecanografías:

    /// <reference path="path/to/typings/typings.d.ts" />
    
    import * as _ from 'lodash`;
    
    console.log(_.toUpper('Hello, world !'))
    
  • Si está utilizando un tsconfig.jsonarchivo, asegúrese de incluir su archivo de mecanografía (o no excluirlo, su elección) y haga lo importmismo en el ejemplo anterior.

En el caso de que no haya mecanografía disponible. Tiene dos opciones: escribir el suyo propio en un .d.tsarchivo o ignorar la verificación de tipos de la biblioteca.

Para ignorar por completo la verificación de tipos (esta no es la forma recomendada), importe la biblioteca en una variable de tipo any.

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

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

tscse quejará de que requireno existe. Proporcione nodemecanografía o declaredescarte el error.

Blackus
fuente
2
Respuesta completa con 3 soluciones. +1
Offirmo
Además: incluso funciona ts-nodesiempre que se haga referencia al índice de mecanografía entsconfig.json
Offirmo
Estoy confundido por lo que quieres decir con "declararlo para descartar el error". ¿Necesito hacer este cambio en el módulo que estoy intentando importar?
Slug
1
Esta respuesta está muy desactualizada. Vea mi nueva respuesta a continuación stackoverflow.com/a/53786892/587407
Offirmo
50

[2018/12] Nueva y actualizada respuesta a esta pregunta que hice en 2016, que aún muestra mucha actividad a pesar de tener respuestas desactualizadas.

En pocas palabras, TypeScript requiere información de tipo sobre el código de su paquete (también conocido como " archivos de declaración de tipo ", también conocido como "mecanografía") y le dice con razón que de otro modo estaría perdiendo todo el sentido de TypeScript. Hay varias soluciones para proporcionarlas o rechazarlas, enumeradas aquí en orden de mejores prácticas:


Solución 0 : el módulo ya proporciona las tipificaciones. Si su package.json contiene una línea como esta:

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

ya está habilitado para TypeScript. Lo más probable es que no sea el caso si está leyendo esta página, así que continuemos ...


Solución 1 : use mecanografía contribuida por la comunidad de DefinitelyTyped . Para un módulo "foo", intente esto:

npm add -D @types/foo

si funciona, premio gordo! Ahora tiene la mecanografía y puede usar su módulo. Si npm se queja de que no puede encontrar el módulo @ types / foo, continuemos ...


Solución 2 : proporcione mecanografía personalizada sobre este módulo. (con opción de hacer cero esfuerzo)

  1. Cree una carpeta llamada "typings-custom" en la raíz de su proyecto
  2. Haga referencia al contenido de esta carpeta en su tsconfig.json:
"include": [
    "./typings-custom/**/*.ts"
]
  1. Cree un archivo con este nombre exacto: foo.d.ts [foo = el nombre del módulo] con el contenido:
declare module 'foo'

Su código TypeScript debería compilarse ahora, aunque sin información de tipo (TypeScript considera el módulo foo de tipo "cualquiera").

También puede intentar escribir la información del tipo usted mismo, mirando el documento oficial y / o ejemplos de DefinitelyTyped . Si lo hace, piense en contribuir con sus mecanografías directamente en el módulo (solución 0, si el autor del módulo acepta) o en DefinitelyTyped (solución 1)

Offirmo
fuente
1
@Offirmo, ¡también podemos declarar múltiples mecanografías personalizadas en un solo archivo! Entonces, no hay necesidad de múltiples archivos (¿tal vez?).
lazycipher
El paso 2. Reference the content of this folder in your tsconfig.json:da el siguiente error: Unknown compiler option 'include'.
Sumit
1
@Sumit no es una opción del compilador, debería ser un hermano decompilerOptions
Offirmo
22

Probablemente te falten los archivos de declaración .

Consulte DefinitelyTyped para obtener más información.


Prueba esto:

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

Ahora puede importar archivos.

import _ from 'lodash';

Si el módulo que está importando tiene varias exportaciones , puede hacer esto:

import { Express, Router } from 'express';

Si el módulo que está importando "no tiene una exportación predeterminada" , debe hacer esto:

import * as http from 'http';
Derek Soike
fuente
¿Por qué tenemos que usar * as _y no solo _ from 'lodash'como en el código ES6?
JohnnyQ
@JohnnyQ Buen punto. Usar import _ from 'lodash';es mejor en este caso. Actualicé mi respuesta para mostrar diferentes formas de importar y por qué las usaría.
Derek Soike
1
El * as _ es necesario si el módulo no tiene ninguna exportación predeterminado. El compilador tsc advertirá de esto.
user2867342
Por "sin exportación predeterminada", ¿eso significa que no se han definido tipos de Typecript (es decir, importar un módulo JavaScript simple)? Soy nuevo en JS / Typecript ...
Big Rich
2
@BigRich "Sin exportación predeterminada" significa que el módulo no tiene una export default <...>declaración. Eche un vistazo a la sección "Exportaciones predeterminadas" de la documentación de los módulos de TypeScript .
Derek Soike
4

Funcionó para mí.

  1. Crea una carpeta llamada "mecanografía".
  2. En la carpeta de mecanografía, cree un nombre de archivo module-name.d.ts . Contiene:

    declare module "module-name";

  3. En tsconfig.json, consulte la carpeta

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

Quynh Ngo
fuente
¡Hola! Gracias por contribuir. Este método ya está incluido en mi respuesta y debe usarse solo como último recurso.
Offirmo
El paso 3:, In tsconfig.json, refer to the folderda el siguiente error:Unknown compiler option 'typesRoots'.
Sumit
1
@Sumit en mi caso, "typesRoots" está dentro de "compilerOptions"
Quynh Ngo
1
Es typeRoots, no typesRoots, y debería estar dentro de compilerOptions
CM
0

Recibí este error y ninguna de las respuestas me funcionó, pero descubro algo cuando quieres trabajar con el módulo de nodo en mecanografiado, instálalo como

$npm install @types/<module_name>

por ejemplo

npm install @types/cheerio

en lugar de decir

npm install cheerio
Crispen Gari
fuente