当前位置: 首页 > news >正文

阮一峰《TypeScript 教程》学习笔记——模块

1. 一段话总结

TypeScript 模块是指包含 import 或 export 语句的文件(无 export 需加export {}强制为模块),模块内部成员默认仅内部可见,对外暴露需用export,外部使用需用import;TS 特支持类型导入导出(如import type仅导入类型、export type仅导出类型),并通过importsNotUsedAsValues编译选项控制类型导入语句的编译行为;同时兼容 CommonJS 模块,用import = require()导入、export =导出;模块定位分Classic 方法(以当前脚本路径为基准)和Node 方法(模拟 Node.js 加载逻辑),支持通过baseUrl/paths/rootDirs进行路径映射;编译时可通过--traceResolution查看定位过程、--noResolve限制仅处理命令行传入模块。


2. 思维导图

在这里插入图片描述


3. 详细总结

一、模块基础

  1. 模块定义

    • 任何包含 importexport 语句的文件即为模块;无 export 但需作为模块(内部成员私有)时,需添加空导出语句:export {}(无实际作用,仅标记为模块)。
    • 模块拥有独立作用域,内部变量、函数、类默认仅内部可见,对外暴露需用 export,外部使用需用 import
  2. TS 模块核心特性

    • 支持类型的导入与导出(区别于 JS 仅导出值),示例:
      // 导出类型
      export type Bool = true | false; 
      // 导入类型
      import { Bool } from './a'; 
      let foo:Bool = true;
      
    • 模块导入可省略后缀名(TS 自动定位 .ts/.d.ts 文件,如 import { A } from './a' 定位到 ./a.ts)。
  3. 模块编译

    • 多文件编译:tsc a.ts b.ts(分别生成 a.js/b.js);仅编译入口文件时,TS 自动编译依赖(如 tsc b.ts 自动编译其依赖的 a.ts)。
    • 合并编译:用 --outFile 参数将多文件合并为一个(如 tsc --outFile result.js b.ts)。

二、类型导入与导出(TS 特有)

为区分“类型”与“值”的导入导出,TS 提供专属语法,避免混淆:

操作类型语法示例说明
导入类型(方式1)import { type A, a } from './a'type A 标记导入的是类型,a 是值
导入类型(方式2)import type { A } from './a'仅导入类型,导入值会报错
导出类型(方式1)export { type A, type B }type 标记导出的是类型
导出类型(方式2)export type { A, B }整行仅导出类型(如导出类的实例类型)
  1. importsNotUsedAsValues 编译选项
    控制“仅导入类型”的 import 语句在编译后的处理方式,有3个取值:
选项值编译行为示例(编译前:import { TypeA } from './a'
remove默认值,删除该 import 语句编译后:无此语句
preserve保留语句(仅触发模块副作用,不导入内容)编译后:import './a';
error保留语句,但强制用 import type,否则报错需改为 import type { TypeA } from './a'

三、CommonJS 模块支持(兼容 Node.js)

TS 提供专属语法兼容 CommonJS 模块(与 ES 模块不兼容):

  1. 导入 CommonJS 模块

    • 语法1:import 模块名 = require('模块路径')(推荐,明确 CommonJS 导入);
    • 语法2:import * as 模块名 from '模块路径'(等效于语法1)。
      示例:
    import fs = require('fs'); // 导入 Node.js 的 fs 模块
    const code = fs.readFileSync('hello.ts', 'utf8');
    
  2. 导出 CommonJS 模块

    • 语法:export = 导出对象(等效于 CommonJS 的 module.exports);
    • 限制:仅能通过 import = require() 导入,无法用普通 import
      示例:
    // 导出(a.ts)
    let obj = { foo: 123 };
    export = obj;
    // 导入(b.ts)
    import obj = require('./a');
    console.log(obj.foo); // 123
    

四、模块定位(确定模块文件位置)

模块定位指 TS 如何根据 import 路径找到实际模块文件,分“模块分类”“定位方法”“路径映射”三部分:

  1. 模块分类

    分类路径特征示例
    相对模块//.//../开头./components/Entry../constants/http
    非相对模块无路径信息jquery@angular/core
  2. 两种定位方法
    通过 moduleResolution 编译选项指定,默认规则:模块格式为 CommonJS 时用 Node 方法,否则用 Classic 方法。

    定位方法核心逻辑查找步骤(以导入b为例)
    Classic以当前脚本路径为基准,逐层向上查找1. 当前目录查b.ts/b.d.ts;2. 上级目录重复查找
    Node模拟 Node.js 加载逻辑,优先查node_modules1. 当前目录node_modulesb.ts/b.d.ts;2. 查package.jsontypes字段;3. 查@types/b.d.ts;4. 查b/index.ts;5. 上级目录重复1-4
  3. 路径映射(tsconfig.json 配置)
    手动指定模块路径,解决复杂目录结构下的定位问题,需配合 baseUrl 使用:

    配置字段作用示例配置
    baseUrl指定模块定位的基准目录(必填,如."baseUrl": "."
    paths非相对模块与实际路径的映射(数组可多路径)"jquery": ["node_modules/jquery/dist/jquery"]
    rootDirs指定额外需查找的目录(如国际化目录)"rootDirs": ["src/zh", "src/de"]

五、编译参数(辅助模块定位)

  1. –traceResolution
    编译时输出模块定位的每一步详细过程,用于排查定位失败问题,命令:tsc --traceResolution

  2. –noResolve
    仅处理命令行传入的模块,不自动查找依赖模块。示例:

    # 仅处理 app.ts 和 moduleA.ts,moduleB 未传入会报错
    tsc app.ts moduleA.ts --noResolve
    

4. 关键问题

问题1:TypeScript 中 import type 与普通 import 的核心区别是什么?分别适用于哪些场景?

答案
核心区别在于导入内容的类型编译行为

  1. 导入内容import type 仅能导入“类型”(如接口、类型别名、类的实例类型),导入“值”(如变量、函数、类本身)会报错;普通 import 可同时导入类型和值。
  2. 编译行为import type 导入的类型语句,会根据 importsNotUsedAsValues 选项处理(如 remove 模式下会删除);普通 import 导入值的语句会保留,触发模块副作用(如执行模块内代码)。

适用场景:

  • import type:仅需使用模块中的类型,不依赖模块副作用(如仅用接口定义变量类型);
  • 普通 import:需同时使用模块的类型和值(如既用 fs 模块的类型,又调用 fs.readFileSync 方法)。

问题2:模块定位的 Classic 方法与 Node 方法在查找逻辑上的核心差异是什么?实际项目中如何选择?

答案
核心差异体现在查找基准非相对模块处理

  1. 查找基准:两者对相对模块的查找基准一致(当前脚本路径),但非相对模块的查找逻辑完全不同:
    • Classic 方法:以当前脚本路径为起点,逐层向上查找模块文件(如 import 'b' 查当前目录→上级目录的 b.ts);
    • Node 方法:模拟 Node.js 逻辑,优先在各级 node_modules 目录中查找(如查当前目录 node_modules/b.ts→上级目录 node_modules/b.ts),且会处理 package.jsontypes 字段、@types 目录等。

选择原则:

  • 若项目为浏览器环境(非 CommonJS 模块)(如 ES 模块、AMD 模块),选择 Classic 方法;
  • 若项目为Node.js 环境(CommonJS 模块),选择 Node 方法(默认),确保与 Node.js 运行时的模块加载逻辑一致,避免定位偏差。

问题3:paths 路径映射的配置逻辑是什么?如何通过 baseUrlpaths 配合,解决“长路径导入”问题?请举例说明。

答案
paths 路径映射的核心逻辑是:baseUrl 为基准目录,将“非相对模块名”映射到实际文件路径,支持多路径 fallback(数组第一个路径不存在时查第二个)。

配置步骤与示例(解决长路径问题):
假设项目结构如下:

src/components/Button/index.ts
tsconfig.json

若不配置 paths,导入 Button 需写长路径:import Button from './src/components/Button',配置后可简化为 import Button from '@components/Button',具体配置:

  1. 配置 baseUrl 为项目根目录(tsconfig.json 所在目录):
    "compilerOptions": {"baseUrl": "." 
    }
    
  2. 配置 paths,将 @components/* 映射到 src/components/*
    "compilerOptions": {"baseUrl": ".","paths": {"@components/*": ["src/components/*"] // * 为通配符,匹配任意子路径}
    }
    
  3. 使用简化导入:
    import Button from '@components/Button'; // 等效于 './src/components/Button'
    

原理:TS 会将 @components/Buttonpaths 映射为 src/components/Button,再以 baseUrl.)为基准,定位到 ./src/components/Button/index.ts

http://www.dtcms.com/a/528210.html

相关文章:

  • 第 09 天:文件传输 (SCP, SFTP, rsync, FTP, NFS)
  • pandas 和 numpy相关函数详解
  • 酵母 cDNA 文库:解码基因表达与功能研究的核心工具
  • Win10使用WSL2安装ubuntu22.04
  • macos 下 docker使用方法 新手教程
  • t恤定制网站哪个网站是做红酒酒的
  • 玉林网站建设培训wordpress美术馆插件
  • 一个大型 3A 游戏的开发流程是怎么样的?
  • 智能性能分析:AI大模型识别性能瓶颈并提出改进建议
  • Flutter 中使用 Flame + flame_forge2d 的注意事项清单
  • SpringBoot教程(安装篇):Elasticsearch及可视化工具安装(Windows环境)
  • 华为OD机试双机位A卷 - 商品推荐多属性排序 (C++ Python JAVA JS GO)
  • 延安市违法建设举报网站深圳宝安网站推广
  • Mac Nginx安装、启动、简单命令(苍穹外卖、黑马点评前端环境搭建)
  • 新乡哪有做网站的北京seo执行
  • GitHub等平台形成的开源文化正在重塑林语堂
  • 鸿蒙分布式软总线通信协议详解
  • 建立网站的技术做谷歌seo要发大量文章吗
  • 第7章 muduo编程示例(5)
  • 微软输入法词库拓展600w(win11)
  • 解决虚拟机安装的Ubuntu20.04.6 LTS 不能复制粘贴问题
  • Linux中系统调用sys_access函数的实现
  • 微波加热内部温度场的电磁−热耦合模拟
  • 2024ICPC上海
  • 专业制作网站多少钱成品网页网站
  • Linux(LDAP服务)
  • 安卓旧机变服务器,KSWEB部署Typecho博客并实现远程访问:cpolar内网穿透实验室第645个成功挑战
  • 无需云服务的家庭相册:OpenHarmony 上的 Rust 实践
  • OpenHarmony后台服务开发指南:ServiceAbility与ServiceExtensionAbility全解析
  • ARM Cortex-M 向量表详解