Typescript 如何将我们导入的类型定义与相应的实现相关联?

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

当我们使用库类型定义 (.d.ts) 文件时,typescript 如何将我们导入的定义与相应的类型相关联?

例如,如果我们:

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

然后里面 bar.spec.js:

import { expect } from 'chai';

Typescript 现在可以理解 expect 的类型外观了吗?它要经过什么过程才能做到这一点?

在我看来,类型定义相当复杂,具有悠久的演变历史。

在这种情况下,node_modules/@types 是一种内置的 "type root",因此 TS 知道您何时导入非相关模块(例如 "chai" 是非相关的,"./chai" 是相对的)在 node_modules/@types 中寻找定义来解决问题。例如 from "chai" 导致 TS 为定义找到 node_modules/@types/chai/index.d.ts。这就是 TS 知道您可以从该模块导入什么以及这些东西是什么样子的方式。

您可以阅读有关 module resolution in the docs 的更多信息。

如何编写 .d.ts 文件可能很难理解(特别是因为大多数已发布的库 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。所以这就是 TS 知道 import { expect } from "chai" 是什么的方式。

另外值得指出的是,Chai 当前的定义似乎并不完全遵循 latest way to define a UMD module。不过,这并不会使它们以任何方式不兼容。