How to consume npm modules from typescript?

95,045

Solution 1

[2018/12] New, up-to-date, answer to this question I asked in 2016, which stills shows a lot of activity despite having outdated answers.

Long story short, TypeScript requires type informations about your package's code (a.k.a. "type declaration files" a.k.a. "typings") and rightfully tells you that you would otherwise be losing the whole point of TypeScript. There are several solutions to provide them or opt out of them, listed here in order of best practice:


Solution 0: the module already provides the typings. If its package.json contains a line like this:

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

it is already TypeScript-enabled. It's most likely not the case if you are reading this page, so let's continue...


Solution 1: use community-contributed typings from DefinitelyTyped. For a module "foo", try this:

npm add -D @types/foo

if it works, jackpot! You now have the typings and can use your module. If npm complains that it can't find the module @types/foo, let's continue...


Solution 2: provide custom typings about this module. (with an option to do zero effort)

  1. Create a folder named "typings-custom" at the root of your project
  2. Reference the content of this folder in your tsconfig.json:
"include": [
    "./typings-custom/**/*.ts"
]
  1. Create a file with this exact name: foo.d.ts [foo = the name of the module] with the content:
declare module 'foo'

Your TypeScript code should now compile, albeit with NO type information (TypeScript consider the foo module of type "any").

You can also attempt to write the type information yourself, looking at the official doc and/or at examples from DefinitelyTyped. If you do, think of contributing your typings either directly into the module (solution 0, if the module author accepts) or into DefinitelyTyped (solution 1)

Solution 2

[EDIT] Thanks a lot for this answer! However, as of 2018, it is outdated. Readers, have a look at the other answers.

There are several ways to import modules from npm. But if you don't get typings, tsc will always complain that it can't find the module you are requiring (even if transpiled js is actually working).

  • If you do have typings and do not use a tsconfig.json, use reference to import the typings:

    /// <reference path="path/to/typings/typings.d.ts" />
    
    import * as _ from 'lodash`;
    
    console.log(_.toUpper('Hello, world !'))
    
  • If you are using a tsconfig.json file, be sure to have your typings file included (or not excluded, your choice), and make the import like on the previous example.

In the case when there is no available typings. You have two choices: write your own on a .d.ts file, or ignore type checking for the library.

To completely ignore the type checking (this is no the recommended way), import the library on a variable of type any.

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

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

tsc will complain that require doesn't exist. Provide node typings, or declare it to discard the error.

Solution 3

You're probably missing the Declaration Files.

See DefinitelyTyped for more info.


Try this:

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

Now you can import.

import _ from 'lodash';

If the module you're importing has multiple exports, you can do this:

import { Express, Router } from 'express';

If the module you're importing "has no default export" you need to do this:

import * as http from 'http';

Solution 4

It worked for me.

  1. Create a folder named "typings".
  2. In typings folder, create a file name module-name.d.ts. It contains:

    declare module "module-name";

  3. In tsconfig.json, refer to the folder

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

Solution 5

I've been getting this error and none of the answers worked for me but i figure out something when you want to work with node module in typescript install them as

$npm install @types/<module_name>

for example

npm install @types/cheerio

instead of saying

npm install cheerio
Share:
95,045

Related videos on Youtube

Offirmo
Author by

Offirmo

~12 years of experience in web development in javascript / html / css, big enterprise apps in C++ and embedded network devices in C. Mostly interested in web app development, javascript, Python, C++... SOreadytohelp !

Updated on July 08, 2022

Comments

  • Offirmo
    Offirmo almost 2 years

    I'm giving a shot at typescript. It works fine at the hello world stage. I'm now trying to use a npm module :

    index.ts =

    import _ = require('lodash')
    
    console.log(_.toUpper('Hello, world !'))
    

    This doesn't work :

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

    Looking at typescript documentation and in google didn't help. Other S/O questions are either unanswered (here and here) or unrelated.

    Elements :

    • typescript 1.8 latest
    • Yes, lodash is installed npm i --save lodash and exists in my filesystem (checked)
    • I also did typings i --save lodash
    • variants import * as _ from 'lodash' or const _ = require('lodash') don't work either
    • I tried tweaking tsconfig.json options as suggested in other answers "moduleResolution": "node" and "module": "commonjs" as suggested in some answers, still doesn't work

    How do we consume a npm package in typescript ??

    • Granga
      Granga almost 8 years
      Did you add reference to lodash.d.ts in your index.ts? It should look similar to this: ///<reference path="../typings/lodash/lodash.d.ts"/>
    • Offirmo
      Offirmo almost 8 years
      @Granga It works. Can you add this as an answer ?
    • Granga
      Granga almost 8 years
      Glad it works. Blackus has already added the answer and it specifies what I suggested even better. One note though: When input files are specified on the command line(which is your case), tsconfig.json files are ignored. (source)
  • Offirmo
    Offirmo almost 8 years
    Complete answer with 3 solutions. +1
  • Offirmo
    Offirmo almost 8 years
    Addition: it even works with ts-node as long as the typings index is referenced in tsconfig.json
  • JohnnyQ
    JohnnyQ almost 7 years
    Why do we have to use * as _ and not just _ from 'lodash' as in ES6 code?
  • Derek Soike
    Derek Soike almost 7 years
    @JohnnyQ Good point. Using import _ from 'lodash'; is better in this case. I've updated my answer to show different ways to import and why you would use them.
  • user2867342
    user2867342 over 6 years
    The * as _ is needed if the module has no default export. The tsc compiler will warn of this.
  • Big Rich
    Big Rich about 6 years
    By 'no default export' does that mean no Typescript types defined (i.e. importing a plain JavaScript module)? I'm new to JS/Typescript....
  • Derek Soike
    Derek Soike about 6 years
    @BigRich "No default export" means the module doesn't have an export default <...> statement. Take a look at the "Default exports" section of the Typescript Modules Documentation.
  • Slug
    Slug over 5 years
    Im confused by what you mean to "declare it to discard the error." Do I need to make this change in the module I am trying to import?
  • Offirmo
    Offirmo over 5 years
    This answer is severely outdated. See my new answer below stackoverflow.com/a/53786892/587407
  • Offirmo
    Offirmo about 5 years
    Hi! Thanks for contributing. This method is already included in my answer and should be used only as a last resort.
  • lazycipher
    lazycipher almost 5 years
    @Offirmo, We can also declare multiple custom typings in a single file as well! So, No need for multiple files (Maybe?).
  • Sumit
    Sumit almost 5 years
    Step 2. Reference the content of this folder in your tsconfig.json: gives the following error: Unknown compiler option 'include'.
  • Sumit
    Sumit almost 5 years
    The step 3: In tsconfig.json, refer to the folder, gives the following error: Unknown compiler option 'typesRoots'.
  • Offirmo
    Offirmo almost 5 years
    @Sumit it's not a compiler option, it should be a sibling of compilerOptions
  • Quynh Ngo
    Quynh Ngo almost 5 years
    @Sumit in my case, "typesRoots" is inside "compilerOptions"
  • C.M.
    C.M. about 4 years
    It's typeRoots not typesRoots, and should be inside compilerOptions
  • Offirmo
    Offirmo about 3 years
    This is solution 1 of the accepted answer.
  • Jonathan Tuzman
    Jonathan Tuzman almost 3 years
    When I add the include line, TS no longer recognizes React itself. This module is declared with using 'export =', and can only be used with a default import when using the 'esModuleInterop' flag. except I have ` "esModuleInterop": true` in my TSConfig