user917170
user917170

Reputation: 1641

Referencing momentJs in TypeScript without NPM

Using RequireJs, TypeScript transipling to AMD modules. Not using NPM. I have 'allowSyntheticDefaultImports' set to true.

I have moment.js v2.17.1 in my libs folder copied from the official repo, and have set it up correctly with RequireJS and at runtime it works perfectly, so this is just a TypeScript compile error.

TS2304: Cannot find name 'moment'

I have moment.d.ts from the official repo in my typings folder.

import "moment";

Gives the same error.

import moment = require("moment");

gives TS2307: Cannot find module 'moment'.

Any Ideas?

EDIT: tsconfig.json looks like

{
  "compileOnSave": true,
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "module": "amd",
    "noImplicitAny": false,
    "removeComments": false,
    "preserveConstEnums": true,
    "sourceMap": true,
    "noEmitOnError": false
  },
  "include": [
    "**/*"
  ],
  "exclude": [
    "node_modules",
    "**/*.d.ts"
  ]
}

Upvotes: 1

Views: 973

Answers (2)

user917170
user917170

Reputation: 1641

TL;DR:

Modify the moment.d.ts file from

export = moment;

To

declare module 'moment' {
    export default moment;
}

Discussion:

Looks like the answer lies in tracing the module resolutions, using

tsc --traceresolution'

You can see exactly what it gets up to. For example,

import moment from 'moment'

Looks for moment in TypeScript files only:

File 'C:/Code/Trunk/moment.ts' does not exist.
File 'C:/Code/Trunk/moment.tsx' does not exist.
File 'C:/Code/Trunk/moment.d.ts' does not exist.

Then looks for node packages:

File 'C:/Code/Trunk/node_modules/@types/moment.d.ts' does not exist.
File 'C:/Code/Trunk/node_modules/@types/moment/package.json' does not   exist.
File 'C:/Code/Trunk/node_modules/@types/moment/index.d.ts' does not exist.

As I am using the straight .js file, I need to use the AMD syntax so it looks for something other than just TypeScript files, eg

import moment = require('libs/moment')

Which yields

File 'C:/Code/Trunk/Mobile/Project/scripts/libs/moment.js' exist - use it as a name resolution result.

Success! Almost! Funnily TSC now gives no errors relating to moment, but at runtime I get this error from RequireJS:

Uncaught Error: Load timeout for modules: libs/moment

Which I can only assume is because moment.js doesn't have an AMD export in it, and in my RequireJS config I have:

shim: {
    moment: {
        exports: "moment"
    }
}

Which creates the AMD export for me. So, the issue is that the JS side of things is fine because RequireJS creates it's own export, but the TS side of things doesn't know that so the compiler complains when I try to use it in TS code.

Even specifying the .d.ts file explicitly doesn't work:

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

Gives

error TS2304: Cannot find name 'moment'.

So the issue there is that moment doesn't export itself in the way we consume it, eg a namespace, so the only way I got it to work was to modify the moment.d.ts file from

export = moment;

To

declare module 'moment' {
    export default moment;
}

And it now works perfectly, no imports or anything!

Upvotes: 4

Paul Jerome Bordallo
Paul Jerome Bordallo

Reputation: 1392

I had the same problem once. Try:

import moment from 'moment';

Upvotes: 0

Related Questions