NSwag: Typescript compilation error when using momentjs and TypeScript 3

Using Typescript 3.* and momentjs for dates I get compile time errors.

Calls like moment() generate following error:

Cannot invoke an expression whose type lacks a call signature. Type ‘typeof moment’ has no compatible call signatures.ts(2349) api.ts(9, 1): Type originates at this import. A namespace-style import cannot be called or constructed, and will cause a failure at runtime. Consider using a default import or import require here instead.

replacing moment() calls with moment.default() resolves the issue.

Im using following nswag.json

{ “runtime”: “NetCore21”, “defaultVariables”: null, “swaggerGenerator”: { “fromSwagger”: { “url”: “http://localhost:54408/swagger/v1/swagger.json”, “output”: null } }, “codeGenerators”: { “swaggerToTypeScriptClient”: { “className”: “{controller}Client”, “moduleName”: “”, “namespace”: “”, “typeScriptVersion”: 3.2, “template”: “Fetch”, “promiseType”: “Promise”, “httpClass”: “HttpClient”, “useSingletonProvider”: false, “injectionTokenType”: “OpaqueToken”, “rxJsVersion”: 6.0, “dateTimeType”: “momentjs”, “nullValue”: “Undefined”, “generateClientClasses”: true, “generateClientInterfaces”: false, “generateOptionalParameters”: false, “exportTypes”: true, “wrapDtoExceptions”: false, “clientBaseClass”: null, “wrapResponses”: false, “wrapResponseMethods”: [], “generateResponseClasses”: true, “responseClass”: “SwaggerResponse”, “protectedMethods”: [], “configurationClass”: null, “useTransformOptionsMethod”: false, “useTransformResultMethod”: false, “generateDtoTypes”: true, “operationGenerationMode”: “MultipleClientsFromOperationId”, “markOptionalProperties”: true, “generateCloneMethod”: false, “typeStyle”: “Class”, “classTypes”: [], “extendedClasses”: [], “extensionCode”: null, “generateDefaultValues”: true, “excludedTypeNames”: [], “handleReferences”: false, “generateConstructorInterface”: true, “convertConstructorInterfaceData”: false, “importRequiredTypes”: true, “useGetBaseUrlMethod”: false, “baseUrlTokenName”: “API_BASE_URL”, “queryNullValue”: “”, “inlineNamedDictionaries”: false, “templateDirectory”: null, “typeNameGeneratorType”: null, “propertyNameGeneratorType”: null, “enumNameGeneratorType”: null, “serviceHost”: “.”, “serviceSchemes”: null, “output”: “src/generated/api.ts” } } }

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 15
  • Comments: 24 (10 by maintainers)

Most upvoted comments

Actually the currently generated code seems not to be compliant with ES6. The import statement currently used (import * as moment from "moment") is a module import, and modules are not allowed to be called (i.e. moment() is forbidden). All named exports of moment can be accesed through the importet object. The default export can be called via moment.default() (as far as I understand it) ref1 https://stackoverflow.com/a/35706271/2017490 ref2 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import

In my opinion the correct solution is to change import * as moment from "moment" to import moment from "moment". So we just import the default export and name it moment.

I’m seeing this issue as well (targeting TypeScript 3.2.2 in my application, NSwag is told to use 2.7 as that is the latest option available). I don’t know about any backwards compatibility issues that this change might cause, but simply changing import * as moment from 'moment'; to import moment from 'moment'; makes the errors further down with e.g. moment(data["started"].toString()) go away.

I’m using moment version 2.23.0 FYI

agree changing to import moment from 'moment'; should solve and should also be backwards compatible

This is not a backwards compatible upgrade that I can tell. If your tsconfig.json contains the following, you must do the import moment from 'moment'; default import workflow:

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

If you don’t have the "allowSyntheticDefaultImports", the default import won’t work at all, and you’ll continue to have to use the import * as moment from 'moment';

I can provide you a sample with more details if that helps. I have a suitable workaround for my project (I don’t require the two options noted above). If you do decide to go forward with the change, at least the upgrade path is pretty easy.

I’ve attached some screenshots that I hope help: With the above options, import * error: image

Without the above options, default import error: image

And in case you’re interested, my dependencies for the reproductions:

  "dependencies": {
    "moment": "^2.23.0"
  },
  "devDependencies": {
    "typescript": "^3.2.4"
  }

in my way, just disable esModuleInterop in tsconfig.json

I think that’s not a good idea because we dont want to couple this to tsconfig.json (its also not part of the configuration etc.) maybe we should just add a AllowSyntheticDefaultImports setting to the TypeScript generator?

This is still open 😦 Had the same issue with ts-jest, disabling esModuleInterop works in my case but gives a bunch of warnings when running tests. Workaround:

  1. Keep import * as moment from 'moment'; (autogenerated by nswag)
  2. Update tsconfig.spec.json:
"compilerOptions": {
  "esModuleInterop": false,
  "allowSyntheticDefaultImports": true,
  ...
}

Hope it helps.

Any progress with this issue? as a workaround i now disabled “importRequiredTypes” and added extensioncode for the imports by hand

I tried to test against Typescript 2.9.2 and Typescript 2.7.2. In Typescript 2.9 I could compile, however users with “allowSyntheticDefaultImports”:“true” would indeed be broken.

I couldnot test against 2.7 or older versions, as I get a lot of other errors (tsc checks node_modules, and many configs in tsconfig don’t work).

What I also tested is leaving the import * as moment from "moment" as is and instead changing the moment(xxx) calls to moment.default(xxx). This unfortunatly also does not work with Typescript 2.9 (works with Typescript 3.*)

Based on the above observations its maybe better to think about other alternatives.

I’ve figured out where this issue comes from. In your tsconfig.json, you might have this property set: "allowSyntheticDefaultImports": true,

This apparently causes the TS compiler error. I don’t know if NSwag should do anything to fix this or not, but removing that entry (or setting it to false) got rid of the error for me.