My project's setup includes 'jspm' tool for libraries and 'tsd' tool for typings.
After installing moment's TypeScript d.ts file (these), I can't find a way to load and actually use a moment instance.
In my file (using SystemJS module loading)
/// <reference path="../../../typings/tsd.d.ts" />
import * as moment from "moment";
import * as _ from "lodash";
...
...
const now = (this.timestamp === 0) ? moment() : moment(this.timestamp);
I get a "TypeError: moment is not a function"
The definitions are structured the same as lodash, which works fine, so I don't know what might be the cause.
Can anyone help?
To import moment. js with TypeScript, we can import the whole package with import . import * as moment from "moment"; to import the 'moment' module as moment .
To use Moment. js with TypeScript, we can use the types provided by moment . import * as moment from "moment"; Then in the getDate method, we set the return type of it to moment.
I did the following:
I installed moment
definition file as follows:
tsd install moment --save
Then I created main.ts:
///<reference path="typings/moment/moment.d.ts" /> import moment = require("moment"); moment(new Date());
And I ran:
$ tsc --module system --target es5 main.ts # no error $ tsc --module commonjs --target es5 main.ts # no error
main.js
looks like this:
// https://github.com/ModuleLoader/es6-module-loader/blob/v0.17.0/docs/system-register.md - this is the corresponding doc ///<reference path="typings/moment/moment.d.ts" /> System.register(["moment"], function(exports_1) { var moment; return { setters:[ function (moment_1) { // You can place `debugger;` command to debug the issue // "PLACE XY" moment = moment_1; }], execute: function() { moment(new Date()); } } });
My TypeScript version is 1.6.2.
This is what I found out:
Momentjs exports a function (i.e. _moment = utils_hooks__hooks
and utils_hooks__hooks
is a function, that's quite clear.
If you place a breakpoint at the place I denoted as PLACE XY
above, you can see that moment_1
is an object (!) and not a function. Relevant lines: 1, 2
To conclude it, the problem has nothing to do with TypeScript. The issue is that systemjs does not preserve the information that momentjs exports a function. Systemjs simply copy properties of the exported object from a module (a function is an object in JavaScript too). I guess you should file an issue in systemjs repository to find out if they consider it to be a bug (or a feature :)).
Since version 2.13, moment includes Typescript typings. No need to use tsd
(or typings
) anymore.
In the systemjs.config.js
file, just add the following:
var map = { // (...) moment: 'node_modules/moment', }; var packages = { // (...) moment: { main: 'moment.js', defaultExtension: 'js' }, };
And in the module:
import moment = require('moment')
I had immense trouble getting this to work, as I could not use npm due to proxy restrictions (therefore had to manually install the libraries). Provided the versions of moment and definitelytyped files are installed in appropriate locations in your project, you can get this to work with a bit of fiddling around.
There is a useful note here on the moment.js website on configuring typescript with moment. The key aspect which helped in my case was adding the following in the compilerOptions section of my tsconfig.json file:
"allowSyntheticDefaultImports": true
This works with Angular 2 but shouldn't be specific to it. You're basically just telling the System loader where to find moment.min.js
.
In system.config.js
:
// map tells the System loader where to look for things
var map = {
'app': 'app', // 'dist',
'@angular': 'node_modules/@angular',
'rxjs': 'node_modules/rxjs',
// tell system where to look for moment
'moment': 'node_modules/moment/min'
};
// packages tells the System loader how to load when no filename and/or no extension
var packages = {
'app': { main: 'main.js', defaultExtension: 'js' },
'rxjs': { defaultExtension: 'js' },
// tell system which file represents the script when you import
'moment': { main: 'moment.min.js', defaultExtension: 'js'}
};
In your module:
import moment from 'moment';
OR (Edit 10/13/2016):
import * as moment from 'moment';
Some commenters have posted the import *
syntax above and I had to switch to that as well after some upgrades (not sure why).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With