how does the typescript compiler discover npm pack

2019-08-25 02:01发布

问题:

The typescript compiler can be configured via tsconfig.json. This also offers settings for discovering type definition files with the typeRoots key.

By default:

By default all visible “@types” packages are included in your compilation. Packages in node_modules/@types of any enclosing folder are considered visible; specifically, that means packages within ./node_modules/@types/, ../node_modules/@types/, ../../node_modules/@types/, and so on.

If typeRoots is specified, only packages under typeRoots will be included

Many packages offer their type definitions in a separate @types/<package-name> package. Jquery for example. At the same time, there are packages that ship with bundled type definitions, Firebase does this.

Why can the typescript compiler pick up Firebase definitions without editing the typeRoots setting? These definitions are not located in @types and, as far as I understand, should not be picked up by default.

回答1:

In the publishing docs in TypeScript you see there are two ways to provide types for your users: https://www.typescriptlang.org/docs/handbook/declaration-files/publishing.html

  1. bundling with your npm package, or
  2. publishing to the @types organization on npm.

Bigger libraries like Firebase have their own types, see packages/firebase/package.json#L58 or packages/database/package.json#L68.

Typescripts reads those referenced files in "typings" of all installed packages that are referenced in your code that is being compiled.

The difference between typeRoots and a regular import 'firebase' is :

  1. Once you provide type files in typeRoot those types are always used in the compilation process (automatic inclusion). This is great for libraries the change the global context, like jQuery, node, etc. They provide global functions that could otherwise not easily be picked up.

  2. You import it explicitly by saying import {Foo} from 'bar'. If bar package has a typing property in its package.json, Typescript will pick it up additionally to those in typeRoots.

The documentation says this:

Keep in mind that automatic inclusion is only important if you’re using files with global declarations (as opposed to files declared as modules). If you use an import "foo" statement, for instance, TypeScript may still look through node_modules & node_modules/@types folders to find the foo package.