Reputation: 29414
I have the following file structure:
(You can clone my GitHub repo to reproduce the error.)
client.ts
|
|-- references lib-a/lib-a.ts
| |
| |-- references lib-a/lib-c.d.ts
|
|-- references lib-b/lib-b.ts
|
|-- references lib-b/lib-c.d.ts (equal to lib-c.d.ts)
lib.c.d.ts:
declare module "lib-c" {
interface LibC {
dummyAttribute: number;
}
}
Compiling client.ts
obviously leads to an error because the same dummyAttribute is declared twice.
lib-b/lib-c.d.ts(3,9): error TS2300: Duplicate identifier 'dummyAttribute'.
Is there any way to force the TypeScript compiler to ignore this error or to "limit" the search for duplicates to one level?
Without touching the compiler, I can only imagine a solution which leads to a situation where lib-a and lib-b are pointing to the same (not to an equal) lib-c file. This is possible via:
lib-a/lib-c.d.ts
and placing a symlink to point to lib-b/lib-c.d.ts
.Point 1 works, of course.
Point 2 didn't work for me. After executing mklink lib-b/lib-c.d.ts lib-a/lib-c.d.ts
(on Windows), the TypeScript compiler still outputted the same duplicate identifier error.
How can I reference two modules referencing equal (but not the same) dependencies themselves?
Upvotes: 1
Views: 624
Reputation: 250822
The solution to this is to ensure that dependencies are managed in a predictable way.
For example, if you use .d.ts
files from Definitely Typed and load them through NuGet, they use package dependencies to ensure you only get one copy of each dependency.
Let's take jQuery as an example.
If we packaged jQuery along with each library that needed it, we would end up exactly in the situation you describe:
- /Scripts
- - /jqueryui
- - - jquery.ui.d.ts
- - - jquery.d.ts
- - /jquerymobile
- - - jquerymobile.d.ts
- - - jquery.d.ts
This causes a problem because this introduces duplicate definitions. In the case of "they are both the same library" you might argue that you want to ignore them, but if two entirely different libraries were competing for the same name in the global namespace, you are going to get runtime problems.
To solve the case that you describe, when installing the NuGet packages for jQuery UI and jQuery mobile (as in the example above), you actually end up with the following result:
- /Scripts
- - /jqueryui
- - - jquery.ui.d.ts
- - /jquerymobile
- - - jquerymobile.d.ts
- - /jquery
- - - jquery.d.ts
And this is the correct way to share a dependency.
This structure is also reflected in the Definitely Typed repository, so both jQuery UI and jQuery mobile point to the same relative jQuery definition.
I'm not sure how something can be "equal but not the same" as in your question - perhaps you have libraries depending on different versions of the same thing... the answer to that question will largely depend on how you are solving the runtime problem (for example, if you are using two versions of jQuery, you are probably assigning one version to a different name in the global scope to avoid the clash, in which case you'd need a modified version of jquery.d.ts with that global name too).
Upvotes: 3