Middy: [Typescript]: TypeError: middy.default is not a function

Created on 6 Jun 2018  路  20Comments  路  Source: middyjs/middy

Typings shows that middy.default exists.

type-systems

Most helpful comment

The typings file should export middy like this:

export = middy;

instead of

export default middy;

And use like the following in typescript projects

import * as middy from '@middy/core';

All 20 comments

The typings file should export middy like this:

export = middy;

instead of

export default middy;

And use like the following in typescript projects

import * as middy from '@middy/core';

@ossareh, @nnyegaard, @peterjcaulfield, @joseSantacruz can you have a look into this?

As far as I can tell there is no meaningful difference between export default middy and export = middy, they're literally the same from my experience.

I don't have any work underway that uses the v1.x branch; @chanlito you're using the v1.x branch from what I can tell, but can you confirm that please? Also could you share your tsconfig.json too? That'll help me repro what you're seeing and consider whether the approach is correct or not.

I'm using the v1 branch

but i'm doing:

import middy from "@middy/core"; import cors from "@middy/http-cors"

and using tsconfig:

{ "compilerOptions": { "module": "commonjs", "target": "es6", "lib": ["es6", "dom", "es2015"], "moduleResolution": "node", "rootDir": "./src", "sourceMap": true, "allowJs": true, "noImplicitAny": true, "noUnusedLocals": true, "noImplicitThis": true, "strictNullChecks": true, "noImplicitReturns": true, "preserveConstEnums": true, "suppressImplicitAnyIndexErrors": true, "forceConsistentCasingInFileNames": true, "outDir": "dist", "allowSyntheticDefaultImports": true, "esModuleInterop": true }, "include": ["./src/**/*.ts"], "exclude": ["node_modules"], "types": ["typePatches"] }

where I think specifically:

"allowSyntheticDefaultImports": true, "esModuleInterop": true

Allows me to import like that.
Else I think it should be import * as middy from "@middy/core";

@nnyegaard just by adding "esModuleInterop": true, fixed the problem, but do we really want everyone to use it like that?

@chanlito No I think we should support the two ways:

import * as middy from "@middy/core"
import middy from @middy/core

Sadly import in the javascript worlds is a bit "weird" atm since NodeJS has their require and they don't support the import keyword yet.

Also Babel handles default exports different then Typescript, because Babel don't follow the standard (If i remember correctly).

I will take a look later or tomorrow at scenario 1

Just a note. I think you could also do a const middy = require("middy") and that would work too. I personally don't do that since import is soon the standard in javascript, but the "correct" way in NodeJS would still be the require keyword. (And TS just transpile import to require)

Okay I just tried with a new application using the following:

Typescript 2.9.1
middy/core 1.0.0-alpha.8

using this tsconfig:
{ "compilerOptions": { "target": "es5", "module": "commonjs", "strict": true, "esModuleInterop": false } }

and I was able to use the syntax:
import middy from "@middy/core"; import cors from "@middy/http-cors";

without problems:
import middy from "@middy/core";
import cors from "@middy/http-cors";

export const main = middy(async () => { return {}; }).use(cors());

If I use import * as middy from "@middy/core";

I would have to select the default export (as expected):
import * as middy from "@middy/core";
import cors from "@middy/http-cors";

export const main = middy.default(async () => { return {}; }).use(cors());

Does this also align with your expeditions @chanlito ?

I'm targeting es2017 since lambda already using node 8.

Okay just tried to change target to es2017 no change.

My guess would be that we could export the function and to a default export so that both cases are handled, but I would needed to test that.

I can do that tomorrow.

Can you try with the following config?

{
  "compilerOptions": {
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "strict": true,
    "target": "es2017"
  },
  "exclude": ["node_modules"]
}

C:
but do we really want everyone to use it like that?

N:
No I think we should support the two ways

@chanlito / @nnyegaard - can either of you explain why using esModuleInterop is not desired in this case?

The babel team recommends pushing out ECMAScript modules when targeting node. Also I read the TS 2.7 Release Notes on this subject to additionally be supporting the use of import middy from "@middy/core".

What am I missing here? Is this primarily so people don't have to change their config to use this library? Would it be more simple to be opinionated about how our code is written, and ensure good guidance is available in the readme for typescript users?

I want to stay away from any decision regarding how we should support TypeScript from a technical standpoint (I know very little about TypeScript), but i totally agree with this statement by @ossareh:

Would it be more simple to be opinionated about how our code is written, and ensure good guidance is available in the readme for typescript users?

I just ran into this issue, but my knowledge of TypeScript is limited.

import middy from "@middy/core";

resulted in TypeError: core_1.default is not a function

Adding esModuleInterop worked, but I wonder if this should be needed?

Full setup:

import middy from "@middy/core";
import httpEventNormalizer from "@middy/http-event-normalizer";
import { pingHandler } from "./pingHandler";

const ping = middy(pingHandler)
  .use(httpEventNormalizer());

module.exports = { ping };
{
  "compilerOptions": {
    "alwaysStrict": true,
    "sourceMap": true,
    "removeComments": true,
    "target": "es2017",
    "module": "commonjs",
    "lib": [
      "es2017",
      "esnext.asynciterable"
    ],

    // TODO: This is added to make the middy import work, do we need this?
    "esModuleInterop": true
  }
}

@drissamri this has been discussed above; we've decided that for now it's absolutely fine to use the esModuleInterop option.

After hours of head-pounding fun I discovered it's also critical to specify:
"module": "commonjs", if you want to actually run it with Node.js (v12 at the time)

Hello @hashbrown, would you like to submit a PR proposing this change? :)

I don't think there is any change that needs to be made. I was just hoping to leave a hint for others who come across the thread. The focus is on the specification of "esModuleInterop": true. All the example configs offered by others happens to include "module": "commonjs".
I ran into a situation where I built my lambda using the serverless aws-nodejs-typescript template which does not specify "module" in ts.config and so I think it defaults to es6.

Disclaimer: I an experienced developer but pretty new to modern web development (node,modules,bundlers,webpack,etc), YMMV!

Thanks for your reply @hashbrown. I was thinking more about updating the documentation. We have a section on typescript and it would be good to cover common issues or configuration options that are not there yet. Do you think that's valuable? I am thinking on the line "What could have saved you one hour of head banging?", if that makes sense :)

That would be great. It is hard to know what audience to target and how much knowledge to assume. Because I was not really familiar with web development, I didn't understand modules/bundlers, and was new to NodeJS and Typescript, and they definitely have some inconsistencies in what they support. Since middy is going to be Node/Lambda/Backend specific, it's good to focus on what parts of Typescript might need to be tweaked to conform to NodeJs, in this case, requiring the CommonJS module.
The other thing that dawned on me, was why would I ever transpile down, this code won't ever be run in a browser. Why use Webpack at all? Turns out it seems useful for "tree-shaking" not sure what else.
Just random thoughts for you. Thanks!

I'm going to close for now. All ts definitions will be redone in middy v2. I will need help, as I don't know TS, please post on https://github.com/middyjs/middy/pull/587 if you can.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

michalorman picture michalorman  路  7Comments

wrumsby picture wrumsby  路  7Comments

MaxVynohradov picture MaxVynohradov  路  4Comments

lmammino picture lmammino  路  4Comments

willfarrell picture willfarrell  路  3Comments