blueprint: TypeError: moment is not a function

It seems that moment@2.14 exports moment as a function by default but it’s being imported with the syntax import * as moment from 'moment', yet this file https://github.com/palantir/blueprint/blob/master/packages/datetime/src/common/dateUtils.ts #calls moment as a function in multiple places, which leads to this error. Has anyone seen this or been able to reproduce? Might be missing something here…

Also obligatory shoutout for the awesome lib, thanks for all your hard work.

Bug report

  • Package version(s): 1.14
  • Browser and OS versions: OSX El Capitan

Steps to reproduce

  1. Import DateRangeInput and pass in valid dates

Actual behavior

TypeError: moment is not a function is thrown

Expected behavior

Should not throw an error.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 6
  • Comments: 34 (6 by maintainers)

Commits related to this issue

Most upvoted comments

My guess is it’s the way it’s being imported here https://github.com/palantir/blueprint/blob/master/packages/datetime/src/common/dateUtils.ts#L8, which I thought pulls the export into a new object, which I can reproduce locally. Importing like import moment from 'moment' pulls in a function.

So definitely, to get moment work as a function, if you are using ES6 and babel, you must import it in this way: import moment from 'moment' and not, as written in the documentation import * as moment from 'moment'

The source of moment uses export default, but the transpiled code ends up as module.exports = ..., meaning that the obnoxious export = ... syntax in the typings is correct, despite what the original source would have you believe, and import * as moment from 'moment' is correct as long as you aren’t using allowSyntheticDefaultImports.

This isn’t resolved though really, as tests should be agnostic and not force you to have to change how you import into modules for them to work.

Can we re-open this please?

Super hacky, but this is how I solved my problem with moment/typescript/webpack:

let moment = require("moment");
if ("default" in moment) {
    moment = moment["default"];
}

This isn’t resolved though really, as tests should be agnostic and not force you to have to change how you import into modules for them to work.

Can we re-open this please?

I can confirm this. When importing with * syntax, I indeed receive an object with moment as a key. This is in line with how moment is being exported as “export default moment” here: https://github.com/moment/moment/blob/develop/src/moment.js#L82

When importing as “import moment from ‘moment’” only then do I receive a function.

import moment from ‘moment’

the solution import moment from ‘moment’ worked for me

import * as temp from ‘moment’; const moment = temp[“default”];

2.0.0-rc.3 now uses Typescript’s new esModuleInterop and the latest version of tslib, which should fix any moment import issues.

additionally, datetime@2.0 no longer depends on moment so that should further solve this problem. (timezone still uses moment-timezone though)

I@seansfkelley Using typescript. I downgraded my moment version to 2.14.1 but even then same error. Setting allowSyntheticDefaultImports to false will break other packages in use. My compiler options in tsconfig.json is

"compilerOptions": {
        "noUnusedParameters": true,
        "noUnusedLocals": true,
        "skipLibCheck": true,
        "noEmit": true,
        "target": "es6",
        "module": "commonjs",
        "noImplicitAny": false,
        "sourceMap": true,
        "inlineSourceMap": false,
        "inlineSources": false,
        "preserveConstEnums": true,
        "moduleResolution": "node",
        "experimentalDecorators": true,
        "jsx": "preserve",
        "lib": [
            "dom",
            "es5",
            "es6",
            "es7",
            "es2017.object"
        ],
        "allowSyntheticDefaultImports": true,
        "baseUrl": "./",
        "paths": {
            "ArchApp/*": [
                "src/*"
            ]
        }
    },

import * as moment from ‘moment’

can not work for me still not working…

The root cause is probably an unfortunate combination of compiler flags, possibly across languages/compilers, causing a disconnect between what you think you’re writing and what is actually coming out the other end.

@opavader / @zsherman are you using Typescript or plain Javascript? Babel also does some weird stuff around these “synthetic defaults” (which I think causes more problems than it solves), so I’d poke around the transpiled output of your project, Blueprint and your version of moment to see which ones are in agreement and which are importing the wrong thing.

Word “require” makes my ionic app execution fail (ts error) with @wshaver solution.

Also worth noting that moments module.exports is not a function, but as per es6 module export spec, it is an object with moment assigned to the default key.