Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to set up a project to be provide shared interfaces/implementations for other projects #1055

Closed
kbirger opened this issue Feb 18, 2020 · 9 comments
Labels

Comments

@kbirger
Copy link

kbirger commented Feb 18, 2020

Steps to Reproduce the Problem

This small test repo minimally reproduces the issue I'm seeing. It is using some packages provided for developing VS Code extensions. There is one package meant to be used for the client, and one for the server. The each define some of the same types using separate, but seemingly compatible definitions. In this case, the problem type is RequestType.

  • clone the repo
  • run npm install
  • run npm run compile (sanity check; this should pass)
  • run npm run webpack

Expected Behaviour

  • ts-loader should be able to load types the same way as the regular tsc compiler

Actual Behaviour

  • webpack fails, even though compile succeeds

ERROR in \webpack-shared-test\client\src\extension.ts
./src/extension.ts
[tsl] ERROR in \webpack-shared-test\client\src\extension.ts(18,18)
TS2769: No overload matches this call.
Overload 1 of 3, '(type: RequestType0<NoConfigResult, void, unknown>, handler: RequestHandler0<NoConfigResult, void>): void', gave the following error.
Argument of type 'RequestType<NoConfigParams, NoConfigResult, void, void>' is not assignable to parameter of type 'RequestType0<NoConfigResult, void, unknown>'.
Types of property '_' are incompatible.
Type '[NoConfigParams, NoConfigResult, void, void, _EM] | undefined' is not assignable to type '[NoConfigResult, void, unknown, _EM] | undefined'.
Type '[NoConfigParams, NoConfigResult, void, void, _EM]' is not assignable to type '[NoConfigResult, void, unknown, _EM]'.
Types of property '1' are incompatible.
Type 'NoConfigResult' is not assignable to type 'void'.
Overload 2 of 3, '(type: RequestType<NoConfigParams, NoConfigResult, void, void>, handler: RequestHandler<NoConfigParams, NoConfigResult, void>): void', gave the following error.
Argument of type 'import("/webpack-shared-test/interfaces/node_modules/vscode-jsonrpc/lib/messages").RequestType<import("/webpack-shared-test/interfaces/out/index").NoConfigParams, import("/webpack-share...' is not assignable to parameter of type 'import("/webpack-shared-test/client/node_modules/vscode-jsonrpc/lib/messages").RequestType<import("/webpack-shared-test/interfaces/out/index").NoConfigParams, import("/webpack-shared-te...'.
Types have separate declarations of a private property '_method'.
Overload 3 of 3, '(method: string, handler: GenericRequestHandler<NoConfigResult, void>): void', gave the following error.
Argument of type 'RequestType<NoConfigParams, NoConfigResult, void, void>' is not assignable to parameter of type 'string'.

Location of a Minimal Repository that Demonstrates the Issue.

https://github.com/kbirger/webpack-shared-test

Additional info

I have also tried configuring webpack's ts-loader as below:

use: [{
        // configure TypeScript loader:
        // * enable sources maps for end-to-end source maps
        loader: 'ts-loader',
        options: {
          configFile: require.resolve('./tsconfig.json'),
          context: path.resolve(__dirname),
          projectReferences: true
        }
      }]

In an attempt to get it to use the same configuration and load modules the same way. This makes no difference.

I understand this is likely an error in how I'm setting up my project, but I cannot find information on how to achieve what I am trying to do.

Also, it seems like overload 2 should be the correct one.

@johnnyreilly
Copy link
Member

I'm really sorry but I can't look into this myself. I notice you're using projectReferences which are not the finished picture in ts-loader yet. You can track progress on them here:

#1028

cc @andrewbranch @sheetalkamat

@kbirger
Copy link
Author

kbirger commented Feb 18, 2020

Thanks @johnnyreilly I meant to remove that line. I had added it later in my debugging. It actually has no impact on the error.

I actually recall seeing that issue (hail Google), but it wasn't super clear to me what is or isn't supported yet.

If anyone can point me to an example of how this sort of setup is supposed to be configured, I can work backwards.

In my actual project I have 3 ts projects: client, server, interfaces, and I just want to avoid duplicating the interfaces.

Honestly, if I can't get this to work, I'll just have a prebuild step physically copy (or link) the files into both client and server before packing, but this seems more elegant

@andrewbranch
Copy link
Contributor

run npm run compile (sanity check; this should pass)

This doesn’t pass for me because vscode-languageclient has a dependency on vscode that isn’t found.

@kbirger
Copy link
Author

kbirger commented Feb 18, 2020

That's strange. I will try again when I get home. I say it's strange because if it's not a peer dependency, then I would think npm pulls it down automatically.

@andrewbranch
Copy link
Contributor

Looking at it again, you/I just need to install @types/vscode. (Actually, vscode-languageclient did the “wrong thing” by making that a devDependency and not a dependency. Libraries are supposed to make their @types packages dependencies to avoid this exact scenario.)

@andrewbranch
Copy link
Contributor

So, I’m not 100% sure why it was working with tsc, but I was able to fix it by moving the dependencies of both client and src up to the root package.json and node_modules. It’s almost always going to have problems to have duplicate type definitions compiled into the same program. I feel like that’s not a very satisfying answer, and there may be some value in investigating why ts-loader is pulling in files differently than tsc here, but I think that long-term, any project structure where you have multiple node_modules folders that ever contain duplicate types between them is going to be more painful than if you can share a single node_modules, whether you’re compiling with tsc or with ts-loader. I have tried to go this route in the past and given up.

If you must treat each of these projects as separate packages with their own package.json and node_modules, I think using a tool like lerna would help, because it hoists common dependencies to the top level for you during development. So you get to keep the conceptual model of separate dependencies, but the reality on your file system essentially reflects the experiment I just did locally where I deleted client/node_modules and interfaces/node_modules.

@kbirger
Copy link
Author

kbirger commented Feb 19, 2020

Thanks @andrewbranch

I suppose I can't think of a reason why I couldn't share modules, but in this case it seems like it is a best practice, and the official guidance for this sort of project.

I suspect that there are sneaky ways around this issue by marking things as any in strategic places, to fool the type system, but who wants to do that? :).

I'll look into lerna, but am still curious if anyone can spot where the issue is.

@stale
Copy link

stale bot commented Apr 19, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Apr 19, 2020
@stale
Copy link

stale bot commented Apr 26, 2020

Closing as stale. Please reopen if you'd like to work on this further.

@stale stale bot closed this as completed Apr 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants