TypeScript 模块的增强和处理嵌套的 JavaScript 文件
学习 TypeScript 中的模块增强基础知识,以及如何为嵌套的 JavaScript 文件添加类型定义。
TypeScript 已成为 JavaScript 生态系统中非常宝贵的补充,超过十年来因其能够为 JavaScript 代码提供类型安全而备受欢迎。
JavaScript 包的类型
为了向后兼容性和灵活性,TypeScript 允许包作者为他们的 JavaScript 包提供类型定义。这些类型定义通常存储在 "DefinitelyTyped" 仓库中。你可以使用 @types
作用域来安装这些类型定义,例如,@types/react
是 React 包的类型定义。
安装这些类型定义之后,你可以自信地使用该包,并确保类型安全性。以下是使用类型安全性定义 React 组件的示例:
模块增强
虽然大多数流行的 JavaScript 包在 @types
作用域中已有现成的类型定义,有些包可能缺少类型定义或类型定义已过时。在这种情况下,TypeScript 提供了一个强大的功能,称为 "模块增强",用于为这些包添加类型定义。我们来看一个示例:
现在你可以在代码中使用这个增强的类型定义了:
模块增强不仅允许你为包添加类型定义,还可以扩展现有的类型定义。例如,你可以为 window
对象添加一个新属性:
并在代码中使用它:
在 之前的文章 中,我们讨论了 React Router 库中的一个类型问题,并且通过扩展和增强现有类型在自定义声明文件中克服了这个影响。
请记住,在使用模块增强时,通过仔细检查 JavaScript 源代码,以确保类型定义的准确性至关重要。不正确的类型定义可能会导致运行时错误。在上述示例中,window.foo
属性必须是存在于 window
对象上的一个字符串。
全局增强
有时你可能会遇到引入全局变量的脚本,你可能希望为这些全局变量提供类型定义,以便在 TypeScript 代码中使用它们。例如,如果你有一个设置了名为 __DEV__
的全局变量的脚本:
你可以为这个全局变量添加类型定义,如下所示:
现在你可以在 TypeScript 代码中使用它了:
通过结合模块增强和全局增强,你甚至可以扩展 JavaScript 原型的类型定义。然而,通常不推荐这样做,因为它可能会污染全局作用域。
模块增强的强大功能允许进行这种扩展,但需要谨慎操作,以防止污染全局作用域。
嵌套的 JavaScript 文件
在前面提到的示例中,我们假设导入可以通过包的入口文件解析。然而,有些包会导出没有相应类型定义的嵌套 JavaScript 文件。考虑一个名为 foo
的包,它具有以下结构:
foo
包导出 index.js
文件作为入口点,并且还导出 bar
目录。
要增强 foo
包的类型定义,你可以创建一个 foo.d.ts
文件:
然而,如果你尝试在 TypeScript 中导入 baz.js
文件,将会遇到错误:
为了增强 baz.js
文件的类型定义,你需要创建一个单独 的 baz.d.ts
文件:
这可以确保 TypeScript 能够定位模块及其关联的类型定义:
为了保持类型定义的有序性,你可以在类型定义文件中模仿包的结构:
这种方法使你的 TypeScript 代码保持结构化并且类型安全,即使是在处理嵌套的 JavaScript 文件时。