Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript npm typings feature changes import semantics

Tags:

typescript

When importing a typings (.d.ts) file using the import x = require('...') pattern the semantics change when a package.json typings entry is used.

For example, the following declaration file imports successfully when no package.json typings entry is used but it generates error TS2656 (Exported external package typings file is not a module) when used with a typings entry:

declare module 'mymodule' {
  export function myfunc(source: string): string;
}

Whereas the same file minus declare module {} imports successfully when used with a package.json typings entry but generates error TS2307 (Cannot find module) when used without a typings entry.

export function myfunc(source: string): string;

Why the change in semantics?

It looks like if you use the new npm typings feature you will have to maintain both npm and non-npm versions of your typings files.

I hit this while trying to use a projects typings file within the project itself (TypeScript does not look in the current project's package.json for typings entries, it seems to confine it's search to./node_modules).

Tested with TypeScript 1.7.5.

like image 687
Stuart Rackham Avatar asked Oct 18 '22 18:10

Stuart Rackham


1 Answers

Per the documentation, the typings key in package.json is an analogue for the main key which points to a single Node.js module. As such, the d.ts file pointed to by typings is also expected to be a single exported module declaration, not a d.ts bundle.

The specific rationale given by the documentation is:

The rationale is that typings should not bring new compatible sources to the set of compiled files; otherwise source files (i.e. .ts files) will be considered by the compiler as part of the user code and will be compiled, and outputs in the package can be overwritten with the resulting .js outputs.

Additionally, loading typings should not pollute global scope by bringing potentially conflicting entries from different version of the same library. Modules have their own scope, and do not pollute the global namespace, if your typings file is not a module, it will be polluting the user global scope, and will cause conflicts with other packages that depend on your package. Similarly /// <references ... /> can bring global declarations into the global scope and should be avoided.

(Personally, like you, I think this implementation is totally wrong and silly. The typings key should have pointed to a single file containing multiple relative declare module './foo' { … } declarations describing the entire package, as a means of avoiding pollution of the filesystem with tons of TypeScript-specific files. Unfortunately, that ship has sailed at this point, so your package just has to have a ton of TypeScript-specific d.ts files side-by-side with your JavaScript modules, plus this redundant description of the main module’s typing.)

like image 127
C Snover Avatar answered Oct 21 '22 17:10

C Snover