How can moment.js be imported with typescript?

TypescriptMomentjsJspm

Typescript Problem Overview


I'm trying to learn Typescript. While I don't think it's relevant, I'm using VSCode for this demo.

I have a package.json that has these pieces in it:

{
  "devDependencies": {
    "gulp": "^3.9.1",
    "jspm": "^0.16.33",
    "typescript": "^1.8.10"
  },
  "jspm": {
    "moment": "npm:moment@^2.12.0"
  }
}

Then I have a Typescript class main.js like this:

import moment from 'moment';
export class Main {
}

My gulpfile.js looks like this:

var gulp = require('gulp');
var typescript = require('gulp-tsb');
var compilerOptions = {
                        "rootDir": "src/",
                        "sourceMap": true,
                        "target": "es5",
                        "module": "amd",
                        "declaration": false,
                        "noImplicitAny": false,
                        "noResolve": true,
                        "removeComments": true,
                        "noLib": false,
                        "emitDecoratorMetadata": true,
                        "experimentalDecorators": true
                      };
var typescriptCompiler = typescript.create(compilerOptions);
gulp.task('build', function() {
  return gulp.src('/src')
    .pipe(typescriptCompiler())
    .pipe(gulp.dest('/dest'));
});

When I run gulp build, I get the message: "../main.ts(1,25): Cannot file module 'moment'."

If I use import moment = require('moment'); then jspm will work and bring in the module when I run the application, but I'm still receiving the build error. I also tried:

npm install typings -g
typings install moment --ambient --save

Instead of making the problem better though, it got worse. Now I get the above error on build as well as the following: "../typings/browser/ambient/moment/index.d.ts(9,21): Cannot find namespace 'moment'."

If I go to the file provided by typings and add at the bottom of the file:

declare module "moment" { export = moment; }

I can get the second error to go away, but I still need the require statement to get moment to work in my main.ts file and am still getting the first build error.

Do I need to create my own .d.ts file for moment or is there just some setup piece I'm missing?

Typescript Solutions


Solution 1 - Typescript

Update

Apparently, moment now provides its own type definitions (according to sivabudh at least from 2.14.1 upwards), thus you do not need typings or @types at all.

import * as moment from 'moment' should load the type definitions provided with the npm package.

That said however, as said in moment/pull/3319#issuecomment-263752265 the moment team seems to have some issues in maintaining those definitions (they are still searching someone who maintains them).


You need to install moment typings without the --ambient flag.

Then include it using import * as moment from 'moment'

Solution 2 - Typescript

You need to import moment() the function and Moment the class separately in TS.

I found a note in the typescript docs here.

>/*~ Note that ES6 modules cannot directly export callable functions
> *~ This file should be imported using the CommonJS-style:
> *~ import x = require('someLibrary');

So the code to import moment js into typescript actually looks like this:

import { Moment } from 'moment'
....
let moment = require('moment');
...
interface SomeTime {
  aMoment: Moment,
}
...
fn() {
  ...
  someTime.aMoment = moment(...);
  ...
}

Solution 3 - Typescript

Not sure when this changed, but with the latest version of typescript, you just need to use import moment from 'moment'; and everything else should work as normal.

UPDATE:

Looks like moment recent fixed their import. As of at least 2.24.0 you'll want to use import * as moment from 'moment';

Solution 4 - Typescript

via typings

Moment.js now supports TypeScript in v2.14.1.

See: https://github.com/moment/moment/pull/3280


Directly

Might not be the best answer, but this is the brute force way, and it works for me.

  1. Just download the actual moment.js file and include it in your project.
  2. For example, my project looks like this:
    $ tree
    .
    ├── main.js
    ├── main.js.map
    ├── main.ts
    └── moment.js
  1. And here's a sample source code:

    import * as moment from 'moment';
    
    class HelloWorld {
        public hello(input:string):string {
            if (input === '') {
                return "Hello, World!";
            }
            else {
                return "Hello, " + input + "!";
            }
        }
    }
    
    let h = new HelloWorld();
    console.log(moment().format('YYYY-MM-DD HH:mm:ss'));

 4. Just use `node` to run `main.js`.

Solution 5 - Typescript

I've just noticed that the answer that I upvoted and commented on is ambiguous. So the following is exactly what worked for me. I'm currently on Moment 2.26.0 and TS 3.8.3:

In code:

import moment from 'moment';

In TS config:

{
  "compilerOptions": {
    "esModuleInterop": true,
    ...
  }
}

I am building for both CommonJS and EMS so this config is imported into other config files.

The insight comes from this answer which relates to using Express. I figured it was worth adding here though, to help anyone who searches in relation to Moment.js, rather than something more general.

Solution 6 - Typescript

ES6 syntax:

1. install moment

npm install --save moment

2. Import "moment" in your typescript file

import moment from 'moment';

Solution 7 - Typescript

Still broken? Try uninstalling @types/moment.

So, I removed @types/moment package from the package.json file and it worked using:

import * as moment from 'moment'

Newer versions of moment don't require the @types/moment package as types are already included.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionpeinearydevelopmentView Question on Stackoverflow
Solution 1 - TypescriptAidesView Answer on Stackoverflow
Solution 2 - TypescriptKobyView Answer on Stackoverflow
Solution 3 - TypescriptNSjonasView Answer on Stackoverflow
Solution 4 - TypescriptsivabudhView Answer on Stackoverflow
Solution 5 - TypescriptMark BirbeckView Answer on Stackoverflow
Solution 6 - Typescripthardy lutulaView Answer on Stackoverflow
Solution 7 - TypescriptBen WindingView Answer on Stackoverflow