dvabuzyarov / moq.ts

Moq for Typescript
Apache License 2.0
122 stars 10 forks source link

Resolving v10 in TS with Node16 resolution doesn't work #931

Open jakebailey opened 1 year ago

jakebailey commented 1 year ago

In a project that sets moduleResolution to Node16, importing this package fails:

image

Module '"moq.ts"' has no exported member 'Mock'.ts(2305)

This is because the d.ts files don't seem to use valid imports:

Relative import paths need explicit file extensions in EcmaScript imports when '--moduleResolution' is 'node16' or 'nodenext'. Consider adding an extension to the import path.ts(2834)

Looking at angular's packages, they have a bundled index.d.ts rather than one that forwards, so maybe that's how they don't break, but they also don't have to run their code in Node.

Truthfully, I'm not sure what the right path is here; I'm having trouble understanding how your build works. You're also in module=es2022 which is not a good choice for Node (Node16 is), but it's not super clear to me if the angular stuff is controlling outputs or what is going on.

dvabuzyarov commented 1 year ago

I will take a look at it.

dvabuzyarov commented 1 year ago

ESM migration is pretty hard for the entire js community. I choose to proceed with ng-packager(produces APF (angular package format)) as a tool to generate ESM output. As I can see APF provides a wide compatibility for different tools and workflows.

I tested node16 resolution module in one of my internal project and got an issue. It works fine with node and nodenext options.

So far I don't have a good solution for that. Need more time to dig into this.

p.s. I tied to find explanation in typescript documentation how the resolution works (in more detail that it is described) and failed. Maybe you could point me where to look it?

dvabuzyarov commented 1 year ago

A demo project on GitHub also would be a very helpful.

jakebailey commented 1 year ago

Sorry, been busy and forgot about this...

p.s. I tied to find explanation in typescript documentation how the resolution works (in more detail that it is described) and failed. Maybe you could point me where to look it?

This is being worked on, hopefully available rouhgly for the TS 5.1 release-ish.

A demo project on GitHub also would be a very helpful.

It isn't very minimal, but https://github.com/jakebailey/hereby is where I am hitting this; you could bump moq.ts there and then run tsc to see.

I choose to proceed with ng-packager(produces APF (angular package format)) as a tool to generate ESM output. As I can see APF provides a wide compatibility for different tools and workflows.

One thing I think may work out better is to use tsup instead, which will also do the bundling step for you and leave you with a consistent API. Something like: https://github.com/immerjs/immer/pull/1032

I was going to try and send a PR for this, but, I couldn't make heads or tails of the build steps in the repo now that the angular stuff is involved; it seems like more is being used than just the build. One thing's for sure; if you're ever writing a d.ts file by hand, things are likely to go wrong.

dvabuzyarov commented 1 year ago

I will take a look at next weekend

dvabuzyarov commented 1 year ago

I played a little with your repository and managed to reproduce the issue. Working on it.

jakebailey commented 1 year ago

Another tsc-only method is the one used in: https://github.com/tapjs/foreground-child/pull/52

(Though, both tsup and this method have their downsides.)

dvabuzyarov commented 1 year ago

Well, the issue should be fixed. Could you, please check it and give me feedback?

jakebailey commented 1 year ago

Seems like it's working in ESM, thanks. https://arethetypeswrong.github.io/?p=moq.ts%4010.0.6 still shows some issues, namely that you can't import it from CJS anymore. In TS, you get:

Module 'moq.ts' cannot be imported using this construct. The specifier only resolves to an ES module, which cannot be imported with 'require'. Use an ECMAScript import instead.

So, not fully out of the woods, but better!

dvabuzyarov commented 1 year ago

Thank you. I will take a look.

dvabuzyarov commented 1 year ago

Thank for pointing to the tool. Haven't seen it before. The shown issues caused by the typings field in the package.json. The implementations respect the calling environment and typings do not. So for the case when the calling module is commonjs the library typing is marked as esm, because of the package.json type="module", but the implementation is picked up form required clause, as driven by calling environment. Probably it could be workaround by excluding the typings field from package.json and providing .d.ts and .d.mts typings. In this case the tool shows an error that typings are not provided. And as I can see there is no working solution at all.

I didn't manage to reproduce this issue

Module 'moq.ts' cannot be imported using this construct. The specifier only resolves to an ES module, which cannot be imported with 'require'. Use an ECMAScript import instead.

Could you please provide an example?