Skip to content

TypeScript's ecosystem of self-bundled typings does not work with npm #8836

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

Open
falsandtru opened this issue May 26, 2016 · 13 comments
Open
Labels
Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. Suggestion An idea for TypeScript

Comments

@falsandtru
Copy link
Contributor

When npm dependencies have same packages of different versions, tsc throws duplicate identifier errors. TypeScript's ecosystem of packages is weaker than npm, and does not have compatibility with npm. I believe this is a large problem. And this will be a popular problem because npm always install an exact version in resolving dependencies. For example, when depending a@^0.0.2 and a@^0.0.1 as another package's dependency, its project has a@0.0.1 and a@0.0.2. npm can resolve these different versions, but TypeScript cannot.

TypeScript Version:

1.9.0-dev.20160526

@DanielRosenwasser DanielRosenwasser added this to the TypeScript 2.0 milestone May 26, 2016
@DanielRosenwasser DanielRosenwasser added Committed The team has roadmapped this issue Community Tooling This might be better handled by tooling from the community instead of built into TypeScript labels May 26, 2016
@mhegazy mhegazy added the @types Relates to working with .d.ts files (declaration/definition files) from DefinitelyTyped label May 26, 2016
@aluanhaddad
Copy link
Contributor

This is a serious problem. But when you say that

because npm always install an exact version in resolving dependencies. For example, when depending a@^0.0.2 and a@^0.0.1 as another package's dependency, its project has a@0.0.1 and a@0.0.2. npm can resolve these different versions, but TypeScript cannot.

it is important to note that the way npm resolves these transitive dependencies is by recursively installing and resolving packages as nested dependencies. Versioning is handled by directory nesting. This is far from ideal and is part of the reason why tools like jspm exist. I'm bringing this up here, in a npm issue, because I think the problem is broader and that a more abstract solution needs to exist.

@mhegazy
Copy link
Contributor

mhegazy commented Jul 4, 2016

if the declaration files are authored correctly as modules, then there are no issues here. if the declaration file is authored as global, then the conflict in the global scope is what i would expect.

@DanielRosenwasser what did you have in mind marking this as "community tooling"?

@niieani
Copy link

niieani commented Jul 5, 2016

@mhegazy Indeed, there might be global declarations, such as node being dependencies of submodules. Perhaps as a simple solution, TypeScript should disregard such global dependencies in case the parent module already has them included? Might not work in all cases, but it's a good start. A better solution would be to somehow have TypeScript wrap all the modules in a similar fashion to the Typings tool, which prevents conflicts between global dependencies.

@mhegazy
Copy link
Contributor

mhegazy commented Jul 5, 2016

TypeScript wrap all the modules in a similar fashion to the Typings tool, which prevents conflicts between global dependencies.

this is not a viable option. wrapping declarations change their shape and origin and leads to more conflicts down the road. it also changes user code, which makes identifying problems and fixing them much harder.

@mhegazy
Copy link
Contributor

mhegazy commented Jul 5, 2016

@mhegazy Indeed, there might be global declarations, such as node being dependencies of submodules.

not sure i understand what you mean by this.

@aluanhaddad
Copy link
Contributor

@mhegazy Something I didn't think about for a long time was that the declare module "..." syntax, while modeling the shape of external modules, actually introduced another global namespace in which collisions are as problematic as any other. Given how widespread this practice has become, and given how typings automatically wraps declaration files, I think clear guidance is needed on how to author declaration files correctly. Furthermore, and I'm sorry for beating a dead horse here, but if the answer to that question is "you can only use the proper (non-polluting) form with node, otherwise you need to use a hack" then there's a definite problem that needs to be addressed at the language level.

@mhegazy
Copy link
Contributor

mhegazy commented Jul 5, 2016

here is the documentation we are adding to the handbook. take a look and let us know if there is something that is missing: microsoft/TypeScript-Handbook#335

@niieani
Copy link

niieani commented Jul 7, 2016

@mhegazy What I meant is that dependencies or their dependencies might require an older, conflicting version of a given global typing (e.g. node). Will the TypeScript compiler know to distinguish the in their respectable scopes, or will it cause problems, like the OP described?

@mhegazy
Copy link
Contributor

mhegazy commented Jul 7, 2016

no. and that is why packages should not rely on specific versions of an @types package, it should be major.minor.* or major.* or just latest for cases like node.

@sebinsua
Copy link

sebinsua commented Mar 21, 2018

@mhegazy @RyanCavanaugh This seems to still be a problem.

Has anybody put any thought into how this might work?

What TypeScript currently does is not in line with how NPM is meant to work or how it is used in practice. You are able to have multiple versions of a package installed (e.g. library-a@1.0.0 and library-a@4.0.0). Therefore TypeScript needs to be able to determine the correct types for the correct version of each library (whether they are contained against @types or packageJson.types).

We have a situation in which we are writing code within a monorepo. We're writing a library library-d which is dependent on library-b and library-c. library-b uses the older version of library-a but the library-c uses the newer version of library-a. The old version of library-a needed a @types/library-a while the new version has its types within its packageJson.types.

I do not know how I can tell TypeScript to use different @types packages for the different versions of a library, and how to tell it to not use this in the case of the modern library with its types contained within the package. And I also do not know how to stop the types from colliding.

Are we meant to use skipLibCheck? This doesn't seem right at all. Surely TypeScript should be able to determine that these packages are distinct and then provide a way of ensuring the correct types are used for each of them?

Right now it seems that we need to code our way around this (using peerDependencies, adapters, upgrading both libraries at the same time, or entirely avoiding having dependencies in our core libraries.)

@sebinsua
Copy link

sebinsua commented Jul 11, 2018

Coming back to this issue but what I am thinking of doing to solve the problem in the short-term is to use tsconfig.json#paths to ensure TypeScript only imports the types of a specific version of a package (which contains its types internally via package.json#types/typings).

I still think that in the long-term TypeScript should be able to resolve the types of an import depending on what version of a package it refers to (this would be in line with the behaviour of node, npm and yarn).

@RyanCavanaugh RyanCavanaugh added Suggestion An idea for TypeScript Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. and removed @types Relates to working with .d.ts files (declaration/definition files) from DefinitelyTyped Committed The team has roadmapped this issue Community Tooling This might be better handled by tooling from the community instead of built into TypeScript labels Mar 7, 2019
@RyanCavanaugh RyanCavanaugh removed this from the Future milestone Mar 7, 2019
@RyanCavanaugh RyanCavanaugh removed their assignment Mar 7, 2019
@falsandtru
Copy link
Contributor Author

Another problem arose: #31148

@falsandtru
Copy link
Contributor Author

As a response for a label; a proposal to resolve a real problem #31148 caused by this core issue is written in there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

7 participants