Search code examples
typescriptecmascript-6typescript2.2

How does Typescript relate the type definition for what we are importing with the corresponding implementation?


When we use libraries typedefinition (.d.ts) files how does typescript relate the definition of what we are importing with the corresponding type?

For example if we:

npm install @types/chai @types/mocha --save-dev

Then inside bar.spec.js:

import { expect } from 'chai';

Typescript now understand the typed facade for expect? What process does it go through to do this?


Solution

  • Type definitions are pretty complex in my opinion, with a long evolutionary history.

    In this case node_modules/@types is sort of a built in "type root" so TS knows when you import a non-relative module (ex "chai" is non-relative, "./chai" is relative) to look for definitions in node_modules/@types for resolution. For example from "chai" results in TS finding node_modules/@types/chai/index.d.ts for the definition. This is how TS knows what you can import from that module and what those things look like.

    You can read more about module resolution in the docs.

    How the .d.ts file is written can be hard to follow (particularly because most published libraries support several module system flavors simultaneously) but in short chai exports an interface ChaiStatic that describes the shape of the module which includes a member expect of type ExpectStatic. So that's how TS knows what import { expect } from "chai" is.

    Also worth pointing out is that it seems Chai's current definitions don't quite seem to follow the latest way to define a UMD module. This doesn't make them incompatible in any way, though.