Coder Social home page Coder Social logo

Comments (41)

jonmanzo avatar jonmanzo commented on July 26, 2024 8

FWIW I was able to work around setting a resolve alias in the webpack config

alias: {
      deepmerge$: path.resolve(__dirname, 'node_modules/deepmerge/dist/umd.js'),
    }

from deepmerge.

sveyret avatar sveyret commented on July 26, 2024 4

Defining alias in Webpack is working, but just for information, modules may not be in current project directory (case of workspaces for example). So it would be better not to define absolute path in Webpack configuration. This is how I did in my project:

alias: {
  deepmerge$: 'deepmerge/dist/umd.js',
},

from deepmerge.

Tarnadas avatar Tarnadas commented on July 26, 2024 2

Could this be reopenend?
The problem still persists and I don't feel like const merge = require('deepmerge').default is an ideal solution.
My app won't compile when I use import merge from 'deepmerge' with TypeScript 2.8 and Webpack 3.10.0, so it's not just affecting jest tests.

from deepmerge.

ciekawy avatar ciekawy commented on July 26, 2024 2

I just added deepmerge to my Ionic/Angular TypeScript project and hit the

Error:(25, 8) TS1192: Module '"node_modules/deepmerge/index"' has no default export.

The project have lot of external dependencies and it would be great to have this fixed regardless possible specific webpack (or other tools) limitations.

the workaround for me now is to add in tsconfig.json:

"allowSyntheticDefaultImports": true

also to avoid IDE errors I had to add the above also in tsconfig-ng.json which is being used by unit test.

from deepmerge.

richardschneider avatar richardschneider commented on July 26, 2024 1

@TehShrike I'm using webpack. The error is TypeError: deepmerge is not a function.

See code at https://github.com/richardschneider/ipfs-encryption/blob/master/src/keychain.js#L80

from deepmerge.

GioSensation avatar GioSensation commented on July 26, 2024 1

Just to update the issue, I have solved this by importing explicitly the file I want, es.js, like this:

import merge from '../node_modules/deepmerge/dist/es.js';

I am not particularly happy about this, because if the name or path to the file change, the import will break. It is still the best solution I could find.

I have asked a question on StackOverflow to see if anybody had any insights to offer, but no answers thus far.

I guess you can close this issue if you have nothing to add.

Thanks.

from deepmerge.

tomwayson avatar tomwayson commented on July 26, 2024 1

I was also having this problem w/ Jest (also using TypeScript, but using Rollup to bundle my library), and I came up w/ a different solution that might work for other Jest users until jestjs/jest#2704 is merged/released. I created a manual mock that require()s deepmerge and then exports it out:

// __mocks__/deepmerge.ts 
// (where __mocks__ is a sibling to node_modules)

import deepmerge = require('deepmerge')
export default function merge(...args) {
  return deepmerge(...args)
}

Then I just use import merge from 'deepmerge' in my source code. When running tests, Jest resolves that to the above mock, but during builds, Rollup resolves that to the actual ESM build of deepmerge.

FWIW, @TehShrike I think you're doing everything right on the package.main/package.module front. I think my problems would be solved if Jest was able to respect the module field. Also, I'm not using the DefinitelyTyped typings, so ¯_(ツ)_/¯

from deepmerge.

msssk avatar msssk commented on July 26, 2024 1

@sveyret
#121 (comment)

A full-TS option (with better typing as well): dojo/framework/util

from deepmerge.

TehShrike avatar TehShrike commented on July 26, 2024

import * as merge is incorrect - assuming your bundler is picking up the ES module, then you're loading the ESM build of the package, which only exposes a default export. import merge from 'deepmerge' is correct.

I would guess that there is different bundling/module loading happening between typescript and jest. I'm not familiar with either of them, but my clue to you is to make sure that they're both either paying attention to the module field in deepmerge's package.json (if you want them to pick up the ESM version), or they're both ignoring it (if you want them to pick up the UMD version).

from deepmerge.

richardschneider avatar richardschneider commented on July 26, 2024

I'm not using TypeScript, just JS on the browser and on node. v2.0.2 works on node, but fails with the error on a browser. Reverting to v1.5.2 works on both environments.

from deepmerge.

TehShrike avatar TehShrike commented on July 26, 2024

@richardschneider What bundler are you using? What is the error message?

from deepmerge.

TehShrike avatar TehShrike commented on July 26, 2024

I couldn't find any webpack config in that repo, but I'm no Webpack expert anyways.

In any case, I can guess at the problem pretty easily - your Webpack is configured to load in the ESM module, and is probably exposing default exports as a default property instead of the object you get when you require.

There are lots of ways you could fix this - you could const deepmerge = require('deepmerge').default, or you could switch your project over to using ES modules and do import deepmerge from 'deepmerge', or you could configure Webpack to ignore the module setting in package.json and just pull in main, since it looks like you don't care about ES modules, or you could configure Webpack to return the default export as the object returned by require instead of returning { default: deepmerge }.

If you want your un-built code to work in node.js, I'm guessing you'll want to do one of the two latter options.

from deepmerge.

TehShrike avatar TehShrike commented on July 26, 2024

@GioSensation You still haven't responded to my earlier message - it looks like you have two bundler environments, and they're both resolving modules differently. This doesn't have anything to do with this package using Rollup to bundle, it has to do with your bundlers respecting the main vs module fields in package.json.

A quick search of issues in the Jest repo turns up this: jestjs/jest#2702

It looks like somebody in that thread figured out a workaround for Jest.

from deepmerge.

GioSensation avatar GioSensation commented on July 26, 2024

Thanks. I will look into it and wait for the Jest team to integrate that pull request.

Cheers!

from deepmerge.

TehShrike avatar TehShrike commented on July 26, 2024

As long as your bundler respects the module field in package.json (which webpack claims to support), everything should work fine.

The package.json's module field points to es.js, which is a traditional ES module that exports a single default.

The package.json's main field points to umd.js, which is a bog-standard UMD file compatible with CommonJS and AMD bundlers.

Which one of those do you want your bundler to pick up? That is up to your project's configuration.

As far as I know, deepmerge's two entry points are the epitome of bundler-friendliness. Any issues should be the result of a misconfiguration or a bug in the bundler that you're using.

I don't know if it's a configuration issue or a bug, but it sounds like some combination of Typescript + Webpack has an issue out of the box.

from deepmerge.

leoalves avatar leoalves commented on July 26, 2024

@Tarnadas
The issue with typescript is that the types are wrong.

If you edit the file index.d.ts from node_modules/types/deepmerge and change the export from
export = deepmerge; to export default deepmerge you can import it as import deepmerge from 'deepmerge'

If you want to import as import merge from 'deepmerge' you need to replace all references in that file from deepmerge to merge.

I am not sure if the typings reflect the most up to date version of the library. There is only one method that I use and for that one is working.

from deepmerge.

TehShrike avatar TehShrike commented on July 26, 2024

ooooh, is that why people are having difficulty with TypeScript?

Where are people getting these types from? Can somebody update them?

Does Typescript pull from module by default?

from deepmerge.

leoalves avatar leoalves commented on July 26, 2024

There is a single repository that most common libraries types are there. It's mostly updated and maintainted by the community. https://github.com/DefinitelyTyped/DefinitelyTyped. The issue is that a lot of times they are not up to date with the library and this can cause issues when compiling.

In this case the problem is more with how TypeScript import works. TypeScript threats CommonJS/AMD/UMD modules in the same way as ES6 modules. When you do import * as merge from 'deepmerge' is the same as merge = require('deepmerge'). This doesn't work for your library.

The other way would be import merge from 'deepmerge' which is the same as merge = require('deepmerge').default. This would work for your library, but the typescript compiler has a configuration option called noImplicitAny. If this option is enabled the typescript does not compile if the type is any. That's the case for your library since you don't have typings.

This option is not enabled by default, but since @Tarnadas was complaining about compiling issues, I figured that this was enabled for him. I also assumed he was using the types from DefinelyTyped. That's why I suggested changing that file.

from deepmerge.

pacey avatar pacey commented on July 26, 2024

I'm having this issue too but deepmerge is being used by a transitive dependency so I can't change the import/require of the function. Any ideas?

from deepmerge.

TehShrike avatar TehShrike commented on July 26, 2024

I'm at a disadvantage here because I'm not familiar with TypeScript's module resolution. I'm also not terribly motivated to spend a day learning about it to fix this issue :-x

deepmerge offers a good import experience for both CommonJS consumers (setting module.exports to a single function) and ES Module consumers (exporting the function as the default export).

I don't see any reason to change that in order to facilitate TypeScript. Besides, as more modules start shipping ES Modules, this problem will keep happening to TypeScript users.

That said, it would be nice to know how to fix it.

Are the typings on DefinitelyTyped correct? Could they be changed to fix the issue?

Should an issue be opened on TypeScript? A quick search turns up at least a couple issues related to CommonJS/ESM interop ({#3337](microsoft/TypeScript#3337), #2719), there may be some clues in there.

@pacey, does the library that is consuming deepmerge use the require or import syntax? Does the issue only happen when require is used? How does TypeScript decide whether to use main versus module?

If there is some way to work around this TypeScript issue by fiddling with Webpack/Babel config, it would be good to get it on record here.

from deepmerge.

TehShrike avatar TehShrike commented on July 26, 2024

It may also just be an issue with Webpack. webpack/webpack#5756

from deepmerge.

pacey avatar pacey commented on July 26, 2024

Yeah it's quite possible to just be a Webpack issue @TehShrike. I'll try and get webpack/webpack#5756 resurrected!

from deepmerge.

TehShrike avatar TehShrike commented on July 26, 2024

@pacey can you make a bare-bones reproduction in a public repository that is just a single-file app that imports deepmerge and gets bundled with webpack?

from deepmerge.

perry-mitchell avatar perry-mitchell commented on July 26, 2024

I'm also getting this issue, but not with typescript: #97

from deepmerge.

TehShrike avatar TehShrike commented on July 26, 2024

I opened an issue with Webpack: webpack/webpack#6584

from deepmerge.

TehShrike avatar TehShrike commented on July 26, 2024

Cool - that's probably worth putting into the readme until the Webpack issue is fixed.

from deepmerge.

zackypick avatar zackypick commented on July 26, 2024

if you're just extending simple objects you can quickly roll your own solution, e.g:

export const deepObjectExtend = function (target: any, source: any) {

    for (let prop in source) {
        if (prop in target) {
            deepObjectExtend(target[prop], source[prop]);
        } else {
            target[prop] = source[prop];
        }
    }

    return target;
};

from deepmerge.

sasaxing avatar sasaxing commented on July 26, 2024

'is-mergeable-object' should be a dependency not dev-dep, shouldn't it?

from deepmerge.

TehShrike avatar TehShrike commented on July 26, 2024

The output is bundled with rollup before deploying, so is-mergeable-object's code is included in the deployed version. You can see isMergeableObject inlined in the version deployed to npm on unpkg.

from deepmerge.

mesqueeb avatar mesqueeb commented on July 26, 2024

I have a similar problem where it's looking in all places, just not the node_modules:
with

import merge from 'deepmerge'

it gives

ERROR in /Users/-----/.ghq/github.com/mesqueeb/VuexEasyFirestore/src/utils/setDefaultValues.js
Module not found: Error: Can't resolve 'deepmerge' in '/Users/-----/.ghq/github.com/mesqueeb/VuexEasyFirestore/src/utils'
 @ /Users/-----/.ghq/github.com/mesqueeb/VuexEasyFirestore/src/utils/setDefaultValues.js 1:0-29 11:9-14
 @ /Users/-----/.ghq/github.com/mesqueeb/VuexEasyFirestore/src/module/actions.js
 @ /Users/-----/.ghq/github.com/mesqueeb/VuexEasyFirestore/src/module/index.js
 @ /Users/-----/.ghq/github.com/mesqueeb/VuexEasyFirestore/src/index.js
 @ ./src/store/store.js
 @ ./src/store/index.js

Or should I open a new issue?

I too am able to fix the issue by writing

import merge from '../../node_modules/deepmerge/dist/es.js'

instead. But I don't think this is ideal. I'm not sure why this is happening only to deepmerge, not to other npm packages...

from deepmerge.

TehShrike avatar TehShrike commented on July 26, 2024

huh, that's super-weird. That does seem like a separate issue, since it just has to do with resolving the package, instead of returning the CJS versus ESM version of the package.

from deepmerge.

mesqueeb avatar mesqueeb commented on July 26, 2024

@TehShrike
Yeah, I'm not sure what the problem is. Maybe because I'm linking with npm link to this seperate package I'm working on where I use the deepmerge. However, other npm modules work fine there...

I also tried editing the main prop in the package.json of deepmerge to the es version. Didn't work.

Once I am done developing, & rollup my package, i'll let you know if anything has changed.

from deepmerge.

mesqueeb avatar mesqueeb commented on July 26, 2024

@TehShrike
I was able to find exactly what the problem was.

I was working on an npm package which had recently added deepmerge as a dependency.
However through npm link I was testing my npm package inside another package which I was doing a webpack dev hot reload on.

Then it hit me. if I try to npm i deepmerge in this package where I have the webpack running it might work!
And yes it did!

To all people trying to test deepmerge inside another package which is being linked to yet another using webpack hot reload, don't forget to npm i deepmerge in the package having the webpack hot reload enabled.

from deepmerge.

davidanaya avatar davidanaya commented on July 26, 2024

I'm having the same problem as @GioSensation where import merge from 'deepmerge' is working fine in an Angular project but fails when running tests with Jest.

I added

  moduleNameMapper: {
    deepmerge: '<rootDir>/node_modules/deepmerge/dist/es.js',
  },

to my jest.config.js which should be importing then the module from that file instead, and now I get a different error

export default deepmerge_1;
    ^^^^^^

    SyntaxError: Unexpected token export

    > 1 | import merge from 'deepmerge';

So now it seems to be importing the proper file, but still is throwing an error.

from deepmerge.

msssk avatar msssk commented on July 26, 2024

The DefinitelyTyped typedefs are bad. I uninstalled them and added the following to my project and it works:

declare module 'deepmerge' {
	function deepmerge<T>(x: Partial<T>, y: Partial<T>, options?: deepmerge.Options): T;
	function deepmerge<T1, T2>(x: Partial<T1>, y: Partial<T2>, options?: deepmerge.Options): T1 & T2;

	namespace deepmerge {
		export interface Options {
			arrayMerge?(target: any[], source: any[], options?: Options): any[];
			clone?: boolean;
			isMergeableObject?(value: object): boolean;
		}

		export function all<T>(objects: Partial<T>[], options?: Options): T;
	}

	export default deepmerge;
}

If you (deepmerge maintainers) are interested in fixing this within your project, you can include the above in deepmerge/index.d.ts. If you would rather offload the maintenance of TS definitions then perhaps I'll submit a PR to DefinitelyTyped (I'm not totally confident in my changes, but they at least make deepmerge basics work for me):

import deepmerge from 'deepmerge';
const opts: deepmerge.Options;
deepmerge(x, y);
deepmerge.all(x, y);

from deepmerge.

TehShrike avatar TehShrike commented on July 26, 2024

I'm now open to maintaining a type definition in this project, as long as there is a test that can be added to the npm run scripts, similar to the DefinitelyTyped tests.

A PR to this repo would be appreciated!

from deepmerge.

sveyret avatar sveyret commented on July 26, 2024

In the last delivery (2.2.1) a correction was made on the index.d.ts which is making the Typescript import impossible again… You should keep the export default in order to be able to do

import merge from 'deepmerge'

Without this, Typescript users can only do

import * as merge from 'deepmerge'

from deepmerge.

TehShrike avatar TehShrike commented on July 26, 2024

See #124

from deepmerge.

sveyret avatar sveyret commented on July 26, 2024

OK, so this makes sense. But how should we configure Webpack, now, in order not to have the is not a function error? I thought the solution was to take the ES module…

from deepmerge.

TehShrike avatar TehShrike commented on July 26, 2024

There's a workaround in the readme that has worked for some people

from deepmerge.

sveyret avatar sveyret commented on July 26, 2024

OK, will try. Thank you.

from deepmerge.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.