TypeScript 中的 Module
本文次要介绍 TS 中的 module 与 non-modules 的区别;.d.ts
文件的作用;以及模块门路的解析规定;
TS 中规定顶层存在 import、export 关键字的代码文件被认为是一个模块,没有顶层 import、export 的文件认为是个别脚本。
模块与脚本的区别
模块 modules 与脚本 non-modules 存在以下几个方向上的区别,这是 JavaScript 中模块与脚本的区别(TypeScript 同样)。
- 作用域上的区别
<!—->
-
- module 存在本人的作用域。在模块中定义的变量、函数、类都存在于本人的作用域上,内部模块和脚本代码不可见。
- non-modules 运行在 global scope 上。顶层定义的变量、函数、类都存在于全局作用域上。内部模块和脚本均可拜访。
<!—->
- 导出和导入
<!—->
-
- module 应用 import export 关键字来别离管制从其余模块导入代码段(变量、函数、类等)以及导出模块中的代码段。
- non-modules 中定义的函数和变量在全局作用域中,因而不须要额定的导入导出操作,间接可全局拜访。
<!—->
- 代码治理
<!—->
-
- module 便于代码切分组织,可依照抽象层次或者性能进行模块划分,便于代码组织。
- 脚本代码个别都是写在对立的几个文件中,须要留神变量的拜访程序,并且有净化全局作用域的危险须要躲避。
<!—->
- 依赖治理
<!—->
-
- 模块依赖是通过 import 来显示指定依赖关系,容许更好的管制依赖关系,能够升高命名上抵触的可能性。
- 脚本的依赖关系是暗藏的(须要认真浏览代码,逐层 debug 能力剖析分明),脚本依照架子啊的程序执行,脚本之间加载的程序很重要【脚本加载的程序变动可能呈现: 函数未找到,变量未定义等谬误】
<!—->
- 加载时序
<!—->
-
- 模块反对异步加载,加载实现后在进行代码执行,能够缩小 HTML 文档解析上的阻塞。
- 脚本是经典的同步加载,在 HTML 中呈现同步脚本则须要期待代码加载并执行实现后 HTML 解析才继续执行。通常代码中除了局部须要提前执行的代码(权限查看,用户校验等),其余的都放在 HTML 文档的开端进行加载(可显式异步加载)执行。
// oneModule.js
export function foo(params) {//...}
export class Bar {constructor() {//...}
}
// twoModule.js
import {foo, Bar} from './oneModule.js';
export function run(){const ins = new Bar();
// ...
return foo(ins);
}
TS 中模块加载机制
模块之间建设关系是靠 import 和 export 来配合应用的,模块加载的时候门路指定有两种形式一种是相对路径另一种是非相对路径。相对路径依据以后文件地位计算索引找到文件地位,非绝对地位模块导入编译器会从蕴含导入的文件目录开始一次向下级目录遍历,尝试匹配到对应的文件。
.d.ts 文件的用法以及相干内容
在 TypeScript 中,.d.ts
文件通常用来定义 JavaScript 库或模块的类型申明。它们是用于形容已存在的 JavaScript 代码的类型信息的文件,次要形容 JavaScript 模块的构造(导出类的参数类型,函数签名格局等)目标是不便在 ts 代码中进行类型检查和智能感知揭示。当应用 TypeScript 编写代码时,能够应用类型申明文件来取得对 JavaScript 库或模块的类型检查和智能感知反对。这些申明文件通常以 .d.ts
为扩展名。
通过引入适当的类型申明文件,能够有以下帮忙:
- 类型查看:类型申明文件容许 TypeScript 编译器验证代码与申明文件中定义的类型是否匹配。这有助于在开发过程中捕捉潜在的类型谬误,并提供更弱小的动态类型查看。
- 智能感知:类型申明文件为编辑器提供了无关库或模块的类型信息,从而提供了智能感知性能。这使得在编写代码时可能取得主动实现、参数提醒和文档等性能,以减少开发效率。
- 文档化:类型申明文件还能够作为库或模块的文档。通过查看类型申明文件,能够理解库的可用函数、类、接口和类型等详细信息,从而更好地了解和应用它们。
案例,定义一个 worker 来实现 ThreeJS 中数据的解决:
onmessage(params) {
//
const data: Block[] = [];
... 大量计算
// 线程计算实现返回
postMessage({fragments: data}, timestamp: params.timestamp);
}
declare module '*?worker' {
const workerConstructor:{new (): Worker
};
export default workerConstructor
}
import './worker.d.ts';
import Worker from './worker.ts?worker'
function calculateAllBlocks(threadCount: number) {for (let i =0; i< threadCount; i++) {const worker = new Worker();
worker.onmessage = dataParse;
// 传入参数启动线程进行计算
worker.postMessage({..., timestamp: performance.now()});
}
}
function dataParse(workerEvent: MessageEvent) {// 解决线程返回数据}
这样咱们能疾速定义一个 worker.ts 线程解决模块代码,而不须要定义成 js 再作为参数传递进去加载执行。main.ts 模块中应用了 Worker 类型也都非法,起因就是导入了 worker.d.ts 来进行类型解释。worker.d.ts 中应用了一个后缀模块申明通配符也就是“*?worker”,只有在导出模块上加上能通过校验的前后缀能力正确的匹配上(留神 main.ts 中的导入)。TS 中申明通配符只有在导出的时候应用了匹配上的后缀才会应用对应的类型来进行解释指标模块。