How to use the new @types packages for TypeScript typings?

1.6k views Asked by At

I've started to migrate a large existing, namespace and <reference> based TypeScript application to use modules and the @types NPM repository. However, I'm running into problems in every second.

  1. Lots of libraries don't even have typings there.
  2. Lots of libraries have completely outdated typings there.
  3. Lots of libraries have a global typings file, resulting that I cannot import it because TS complains that it's not a module.
  4. When a library has a module shaped typing file correctly included in it's NPM package (like moment.js), TS still seems to be unable to find it, and errors the line import * as moment from 'moment' saying module is not found.

What is the current state of this technique? As I see it at first glance, it seems to be far from being production ready.

What are the hacks and techniques to overcome these issues?

I'm targetting es5 and using es6 as modules configuration. Can this be the problem? As far as I know TS supports the es6 module syntax for es5 output as well.

1

There are 1 answers

2
Daniel Rosenwasser On BEST ANSWER

The current way things are done is definitely production-ready; however, there's a few things which aren't obvious and that isn't your fault.

Let me try to answer your questions one-by-one.

  1. Lots of libraries don't even have typings there.

In TypeScript 2.1, as long as you have a package installed in node_modules and you don't have noImplicitAny turned on, you can just import whatever you want.

If you do want to use noImplicitAny (which I would recommend for any project that you expect to grow over time), you can just always create a declarations.d.ts in your project source folder that declares the modules as you need:

// do anything you want when you import `"foo"` now.
declare module "foo";

// can only access the `hello` export when importing `"bar"`.
declare module "bar" {
    export var hello;
}
  1. Lots of libraries have completely outdated typings there.

You should definitely feel free to send a pull request to DefinitelyTyped, but if you're really strapped for time, you can just use the approach I gave for point (1).

  1. Lots of libraries have a global typings file, resulting that I cannot import it because TS complains that it's not a module.

If you need to use a global declaration file from DefinitelyTyped, and it's not automatically included in your project, you may have to add it to the types field in your tsconfig.json. See my other answer here, but the crux of it is that if you need to include global declarations for the foo and bar packages, and you have @types/foo and @types/bar installed, you can write the following in your tsconfig.json.

{
    "compilerOptions": {
        "types": ["foo", "bar"]
    }
}
  1. When a library has a module shaped typing file correctly included in it's NPM package (like moment.js), TS still seems to be unable to find it, and errors the line import * as moment from 'moment' saying module is not found.

I believe that this has to do with the fact that you're targetting ES6. Try changing your "moduleResolution" option to "node" in your tsconfig.json.

{
    "compilerOptions": {
        "moduleResolution": "node"
    }
}

Sorry that that is a gotcha. The rationale is that the only module loading system that actually has this resolution semantics is CommonJS (the strategy that Node uses). I agree that that could be improved.