256
votes

I tried to use it with typescript bindings:

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

test.ts:

import {moment} from 'moment/moment';

And without:

npm install moment --save

test.ts:

var moment = require('moment/moment');

But when I call moment.format(), I get an error. Should be simple, can anybody provide a command line/import combination that would work?

22
share your error pleasebasarat
If I install moment.d.ts and use import, I get compile error ERROR in .../typings/browser/ambient/moment/moment.d.ts (9,21): error TS2503: Cannot find namespace 'moment'. And if I don't install typings and use require, I get Uncaught TypeError: moment.format is not a functionSergey Aldoukhov
There are far too many old answer here. Please look here: github.com/angular/angular-cli/wiki/…Didia
Hinrich's answer worked for me with ng4 (as of June 2017) stackoverflow.com/a/43257938/1554495tenderloin
SergeyAldoukhov is this still the best answer? surely @Hinrich's is?jenson-button-event

22 Answers

561
votes

Update April 2017:

As of version 2.13.0, Moment includes a typescript definition file. https://momentjs.com/docs/#/use-it/typescript/

Just install it with npm, in your console type

npm install --save moment

And then in your Angular app, import is as easy as this:

import * as moment from 'moment';

That's it, you get full Typescript support!

Bonus edit: To type a variable or property as Moment in Typescript you can do this e.g.:

let myMoment: moment.Moment = moment("someDate");
101
votes

moment is a third party global resource. The moment object lives on window in the browser. Therefor it is not correct to import it in your angular2 application. Instead include the <script> tag in your html that will load the moment.js file.

To make TypeScript happy you can add

declare var moment: any;

at the top of your files where you use it to stop the compilation errors, or you can use

///<reference path="./path/to/moment.d.ts" />

or use tsd to install the moment.d.ts file which TypeScript might find on it's own.

Example

import {Component} from 'angular2/core';
declare var moment: any;

@Component({
    selector: 'example',
    template: '<h1>Today is {{today}}</h1>'
})
export class ExampleComponent{
    today: string = moment().format('D MMM YYYY');
}

Just be sure to add the script tag in your html or moment won't exist.

<script src="node_modules/moment/moment.js" />

Module loading moment

First you would need to setup a module loader such as System.js to load the moment commonjs files

System.config({
    ...
    packages: {
        moment: {
            map: 'node_modules/moment/moment.js',
            type: 'cjs',
            defaultExtension: 'js'
        }
    }
});

Then to import moment into the file where needed use

import * as moment from 'moment';

or

import moment = require('moment');

EDIT:

There are also options with some bundlers such as Webpack or SystemJS builder or Browserify that will keep moment off of the window object. For more information on these, please visit their respective websites for instruction.

51
votes

The following worked for me.

First, install the type definitions for moment.

typings install moment --save

(Note: NOT --ambient)

Then, to work around the lack of a proper export:

import * as moment from 'moment';
29
votes

I would go with following:

npm install moment --save

To your systemjs.config.js file's map array add:

'moment': 'node_modules/moment'

to packages array add:

'moment': { defaultExtension: 'js' }

In your component.ts use: import * as moment from 'moment/moment';

and that's it. You can use from your component's class:

today: string = moment().format('D MMM YYYY');

25
votes

We're using modules now,

try import {MomentModule} from 'angular2-moment/moment.module';

after npm install angular2-moment

http://ngmodules.org/modules/angular2-moment

23
votes

To use it in a Typescript project you will need to install moment:

npm install moment --save

After installing moment, you can use it in any .ts file after importing it:

import * as moment from "moment";

16
votes

For Angular 7+ (Also Supports 8, 9, 10, 11):

1: Install moment by command npm install moment --save

2: Do not add anything in the app.module.ts

3: Just add import statement in top of your component or any other file like this: import * as moment from 'moment';

4: Now you can use moment anywhere in your code. Just like:

myDate = moment(someDate).format('MM/DD/YYYY HH:mm');

14
votes

--- Update 11/01/2017

Typings is now deprecated and it was replaced by npm @types. From now on getting type declarations will require no tools apart from npm. To use Moment you won't need to install the type definitions through @types because Moment already provides its own type definitions.

So, it reduces to just 3 steps:

1 - Install moment which includes the type definitions:

npm install moment --save

2 - Add the script tag in your HTML file:

<script src="node_modules/moment/moment.js" />

3 - Now you can just use it. Period.

today: string = moment().format('D MMM YYYY');

--- Original answer

This can be done in just 3 steps:

1 - Install moment definition - *.d.ts file:

typings install --save --global dt~moment dt~moment-node

2 - Add the script tag in your HTML file:

<script src="node_modules/moment/moment.js" />

3 - Now you can just use it. Period.

today: string = moment().format('D MMM YYYY');
9
votes

with ng CLI

> npm install moment --save

in app.module

import * as moment from 'moment';

providers: [{ provide: 'moment', useValue: moment }]

in component

constructor(@Inject('moment') private moment)

this way you import moment once

UPDATE Angular => 5

{
   provide: 'moment', useFactory: (): any => moment
}

For me works in prod with aot and also with universal

I dont like using any but using moment.Moment I got

Error   Typescript  Type 'typeof moment' is not assignable to type 'Moment'. Property 'format' is missing in type 'typeof moment'.
8
votes

The angular2-moment library has pipes like {{myDate | amTimeAgo}} to use in .html files.

Those same pipes can also be accessed as Typescript functions within a component class (.ts) file. First install the library as instructed:

npm install --save angular2-moment

In the node_modules/angular2-moment will now be ".pipe.d.ts" files like calendar.pipe.d.ts, date-format.pipe.d.ts and many more.

Each of those contains the Typescript function name for the equivalent pipe, for example, DateFormatPipe() is the function for amDateFormatPipe.

To use DateFormatPipe in your project, import and add it to your global providers in app.module.ts:

import { DateFormatPipe } from "angular2-moment";
.....
providers: [{provide: ErrorHandler, useClass: IonicErrorHandler}, ...., DateFormatPipe]

Then in any component where you want to use the function, import it on top, inject into the constructor and use:

import { DateFormatPipe } from "angular2-moment";
....
constructor(.......,  public dfp: DateFormatPipe) {
    let raw = new Date(2015, 1, 12);
    this.formattedDate = dfp.transform(raw, 'D MMM YYYY');
}

To use any of the functions follow this process. It would be nice if there was one way to gain access to all the functions, but none of the above solutions worked for me.

5
votes

If you're okay adding more third-party packages, I used the angular2-moment library. Installation was pretty straightforward, and you should follow the latest instructions on the README. I also installed typings as a result of this.

Worked like a charm for me, and barely added any code to get it working.

5
votes

Not sure if this is still an issue for people, however... Using SystemJS and MomentJS as library, this solved it for me

/*
 * Import Custom Components
 */
import * as moment from 'moment/moment'; // please use path to moment.js file, extension is set in system.config

// under systemjs, moment is actually exported as the default export, so we account for that
const momentConstructor: (value?: any) => moment.Moment = (<any>moment).default || moment;

Works fine from there for me.

5
votes

for angular2 RC5 this worked for me...

first install moment via npm

npm install moment --save

Then import moment in the component that you want to use it

import * as moment from 'moment';

lastly configure moment in systemjs.config.js "map" and "packages"

// map tells the System loader where to look for things
  var map = {
  ....
  'moment':                     'node_modules/moment'
  };
  // packages tells the System loader how to load when no filename and/or no extension
  var packages = {
    ...
    'moment':                       { main:'moment', defaultExtension: 'js'}
  };
4
votes

In addition to SnareChop's answer, I had to change the typings file for momentjs.

In moment-node.d.ts I replaced:

export = moment;

with

export default moment;
4
votes

Moment.js now supports TypeScript in v2.14.1.

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

4
votes

My own version of using Moment in Angular

npm i moment --save

import * as _moment from 'moment';

...

moment: _moment.Moment = _moment();

constructor() { }

ngOnInit() {

    const unix = this.moment.format('X');
    console.log(unix);    

}

First import moment as _moment, then declare moment variable with type _moment.Moment with an initial value of _moment().

Plain import of moment wont give you any auto completion but if you will declare moment with type Moment interface from _moment namespace from 'moment' package initialized with moment namespace invoked _moment() gives you auto completion of moment's api's.

I think this is the most angular way of using moment without using @types typings or angular providers, if you're looking auto completion for vanilla javascript libraries like moment.

3
votes

Try adding "allowSyntheticDefaultImports": true to your tsconfig.json.

What does the flag do?

This basically tells the TypeScript compiler that it's okay to use an ES6 import statement, i. e.

import * as moment from 'moment/moment';

on a CommonJS module like Moment.js which doesn't declare a default export. The flag only affects type checking, not the generated code.

It is necessary if you use SystemJS as your module loader. The flag will be automatically turned on if you tell your TS compiler that you use SystemJS:

"module": "system"

This will also remove any errors thrown by IDEs if they are configured to make use of the tsconfig.json.

2
votes

The following worked for me:

typings install dt~moment-node --save --global

The moment-node does not exist in typings repository. You need to redirect to Definitely Typed in order to make it work using the prefix dt.

2
votes

for angular2 with systemjs and jspm had to do:

import * as moment_ from 'moment';
export const moment =  moment_["default"];

var a = moment.now();
var b = moment().format('dddd');
var c = moment().startOf('day').fromNow();
2
votes

For ANGULAR CLI users

Using external libraries is in the documentation here:

https://github.com/angular/angular-cli/wiki/stories-third-party-lib

Simply install your library via

npm install lib-name --save

and import it in your code. If the library does not include typings, you can install them using:

npm install lib-name --save

npm install @types/lib-name --save-dev

Then open src/tsconfig.app.json and add it to the types array:

"types":[ "lib-name" ]

If the library you added typings for is only to be used on your e2e tests, instead use e2e/tsconfig.e2e.json. The same goes for unit tests and src/tsconfig.spec.json.

If the library doesn't have typings available at @types/, you can still use it by manually adding typings for it:

First, create a typings.d.ts file in your src/ folder.

This file will be automatically included as global type definition. Then, in src/typings.d.ts, add the following code:

declare module 'typeless-package';

Finally, in the component or file that uses the library, add the following code:

import * as typelessPackage from 'typeless-package'; typelessPackage.method();

Done. Note: you might need or find useful to define more typings for the library that you're trying to use.

1
votes

I followed advice to allow allowSyntheticDefaultImports (since there is no export from moment to use for me), using System. Then I followed someone's advice to use:

import moment from 'moment';

With moment being mapped in my system.js config. The other import statements wouldn't work for me, for some reason

1
votes

With systemjs what I did is, inside my systemjs.config I added map for moment

map: {
   .....,
   'moment': 'node_modules/moment/moment.js',
   .....
}

And then you can easily import moment just by doing

import * as moment from 'moment'