Description
This issue is explained in details in #2839
Terminology
Through out this issue, i will be referring to different ways of declaring external modules, here are what i mean by them.
Ambient external module declaration
Module declarations of the form:
declare module "mod" {
....
}
Proper external modules
The other way of writing a declaration of a module, i.e. a declaration file with a top level import
or export
; e.g.:
import { Contract } from ".\core"
export var MyContract: Contract;
Script file
A file that is not a module, i.e. does not include a top level import
or export
. it could however, include ambient external module declarations as described above.
Background
With module resolution work done in #4154 and #4352, it is possible for node package authors to distribute typings with their packages. For these packages, users do not have to independently acquire the typings from definitely typed, but will just import
the package, the the compiler will locate the typings in the package directory (either index.d.ts
or by following typings
property in package.json
in the package directory).
As noted in #2839, for a package author interested in distributing their typings with their package, there are dependencies that they need typings for; the most common would be node.d.ts
, which is possibly referenced by each package.
The way they dependency typing are authored today on definitely typed is using ambient external module declaration; this indicates that these typings exist in the global scope, and thus are susceptible to conflicts. The classic the diamond dependency issue (courtesy of @poelstra):
- myprogram
- mylib
- myutils@1.0
- myotherlib
- myutils@2.0
- mylib
Now, if myUtils.d.ts
uses ambient external module declaration, this is guaranteed to result in re-declaration errors.
Proposal
When resolving an import
target in a node module, it is an error to include files that are not either:
- Proper external modules, or
- A Versioned script file - see below
For proper external modules, there are no conflicts expected, as external modules do no polute the global namespace.
For versioned files, referring to the same library, the compiler will follow a conflict resolution logic picking only the latest copy (as described by @basarat in #2839 (comment)). The files provided on the command line will be allowed to override this conflict resolution policy.
Versioned files
These are files declaring an identity, i.e. a name and a version. A versioned file is expected to contain a comment at the top of the form
/// <library name="myLibraryName" version="1.0.23.2-beta" />
Where the name
field is optional, and if committed, the file name is used instead, and the version
field follows the version definition in http://semver.org/