Skip to content

TypeScript

官方文档:

1,index.d.ts

index.d.ts是 TypeScript 中的一种命名约定,它有特定的用途和意义:

  1. index 部分 :在 Node.js 和许多前端构建工具中, index 文件是一个模块的默认入口点。当你导入一个目录而不是具体文件时(例如 import * from './directory' ),系统会自动查找该目录下的 index 文件。

  2. .d.ts 后缀 : .d.ts 是 TypeScript 的类型声明文件扩展名。这些文件只包含类型信息,不包含实际的 JavaScript 代码实现。它们的作用是:

    • 为 JavaScript 库提供类型定义

    • 允许 TypeScript 编译器理解库的 API

    • 提供代码补全和类型检查功能

在你看到的 VitePress 的 index.d.ts 文件中,它包含了 VitePress 的所有公共 API 的类型定义。这个文件让使用 TypeScript 的开发者能够获得 VitePress API 的类型提示和类型检查。

当其他开发者在他们的项目中使用 VitePress 时,TypeScript 编译器会读取这个声明文件来了解 VitePress 的 API 结构,从而提供更好的开发体验。

2, JavaScript和TypeScript区别

适用场景:

JavaScript 适用场景

  1. 小型项目或原型开发

    • 快速启动,无需配置类型系统
      • 开发周期短,需要快速迭代
  2. 脚本类任务

    • 简单的自动化脚本
      • 一次性的工具脚本
  3. 团队对 TypeScript 不熟悉

    • 学习成本考虑
      • 团队习惯于 JavaScript 开发
  4. 与特定框架集成较好

    • 某些旧框架可能对 TypeScript 支持不完善
  5. 浏览器直接运行的代码

    • 无需构建步骤的简单网页

TypeScript 适用场景

  1. 中大型项目

    • 代码量大,需要更好的组织和维护
      • 多人协作开发
  2. 长期维护的项目

    • 需要良好的代码文档和类型提示
      • 频繁重构和功能迭代
  3. 库和框架开发

    • 提供良好的类型定义给使用者
      • 增强 API 的可发现性和使用体验
  4. 复杂业务逻辑

    • 类型系统帮助捕获潜在错误
      • 减少运行时错误
  5. 团队协作

    • 明确的接口定义
      • 代码自文档化

在 weapp-vite 这样的工具库项目中,使用 TypeScript 是很好的选择,因为它需要提供稳定的 API、支持长期维护,并且需要良好的开发体验。

  1. 类型系统:
javascript
// JavaScript
let name = "张三";
name = 123; // 可以随意改变类型

// TypeScript
let name: string = "张三";
name = 123; // 错误:不能将类型"number"分配给类型"string"
  1. 接口定义:
typescript
// TypeScript 支持接口
interface Article {
  title: string;
  date: string;
  tags: string[];
}

// 使用接口约束对象结构
const article: Article = {
  title: "文章标题",
  date: "2024-01-01",
  tags: ["JavaScript", "TypeScript"]
};
  1. 类型注解:
typescript
// TypeScript 支持类型注解
function calculateTotal(price: number, quantity: number): number {
  return price * quantity;
}

// JavaScript 没有类型注解
function calculateTotal(price, quantity) {
  return price * quantity;
}
  1. 编译时检查:
  • TypeScript 在编译时进行类型检查
  • JavaScript 在运行时才能发现类型错误
  1. 开发工具支持:
  • TypeScript 提供更好的代码提示和重构功能
  • JavaScript 的 IDE 支持相对较弱
  1. 学习曲线:
  • JavaScript 入门更简单
  • TypeScript 需要学习额外的类型系统概念 在你的项目中使用了 TypeScript,这有助于:
  1. 提前发现潜在错误
  2. 提供更好的代码提示
  3. 提高代码可维护性
  4. 更容易进行大型项目开发

commonjs和TypeScript写法

commonjs:

javascript
export const themeConfig: DefaultTheme.Config = {
  nav,
  sidebar,
  // ... 其他配置
}

TypeScript:

typescript
export const themeConfig = {
  nav,
  sidebar,
  // ... 其他配置
} as DefaultTheme.Config;

as是 TypeScript 的类型断言,它的作用是:

  1. 类型检查:告诉 TypeScript 编译器这个配置对象符合 VitePress 的 DefaultTheme.Config 接口定义

  2. 类型提示:在编辑器中可以获得正确的代码提示和类型检查

  3. 类型安全:确保配置对象包含了必要的属性,并且属性值类型正确

两种方式都可以,效果是一样的。第一种是显式类型声明,第二种是类型断言,都能确保类型安全。

3,tsconfig.json 的作用

tsconfig.json 是 TypeScript 项目的配置文件,它起到以下几个关键作用:

主要功能

  1. 定义编译选项 :指定 TypeScript 编译器如何将 TypeScript 代码转换为 JavaScript 代码

    • 目标 JavaScript 版本 (target)

    • 模块系统 (module)

    • 严格类型检查选项 (strict)

    • 输出目录 (outDir)

    -moduleResolution 配置项决定了 TypeScript 如何查找和解析模块

undefined
## "moduleResolution": "node"
这种模式模仿 Node.js 的模块解析机制:

- 对于相对导入路径(以 ./ 或 ../ 开头),会在相对目录中查找
- 对于非相对导入路径,会从当前目录的 node_modules 开始查找,然后逐级向上查找父目录的 node_modules
- 支持 package.json 中的 main 字段
- 适合 Node.js 环境或使用 CommonJS 模块的项目
## "moduleResolution": "Bundler"
这是较新的模式,为现代打包工具(如 Webpack、Vite、esbuild 等)设计:

- 结合了 Node.js 和 ECMAScript 模块解析的特点
- 支持 package.json 中的 exports 字段(包导出映射)
- 更好地支持 ESM 模块规范
- 适合使用现代打包工具的前端项目
  1. 指定项目范围 :通过 include 和 exclude 字段确定哪些文件应该被编译

  2. 配置类型检查 :设置类型检查的严格程度和特性

  3. 路径映射 :通过 paths 配置模块导入路径别名

yaml
// 使用别名导入
import { something } from '@/utils/helpers';

// 不使用别名则需要这样(可能会有很长的相对路径)
import { something } from '../../utils/helpers';

tsconfig.json基础配置

undefined
{
   // 继承根包
   "extends": "../../tsconfig.json",
  "compilerOptions": {
    // 指定生成的JavaScript的版本,ESNext表示使用最新的ECMAScript特性
    "target": "ESNext",
    
    // 指定生成的模块系统,ESNext表示使用最新的ECMAScript模块系统
    "module": "ESNext",
    
    // 指定模块解析策略,Bundler适用于使用打包工具的项目
    "moduleResolution": "Bundler",
    
    // 允许导入JSON文件作为模块
    "resolveJsonModule": true,
    
    // 指定额外的类型声明文件
    "types": [
      "vitest/globals"
    ],
    
    // 允许编译JavaScript文件
    "allowJs": true,
    
    // 启用所有严格类型检查选项
    "strict": true,
    
    // 允许导入没有默认导出的模块时使用默认导入语法
    "allowSyntheticDefaultImports": true,
    
    // 启用CommonJS和ES模块之间的互操作性
    "esModuleInterop": true,
    
    // 跳过对声明文件的类型检查,提高编译速度
    "skipLibCheck": true,
    
    // 生成声明文件(.d.ts)
    "declaration": true,
    
    // 确保文件名大小写一致性
    "forceConsistentCasingInFileNames": true,
    
    // 启用源映射,便于调试
    "sourceMap": true,
    
    // 删除所有注释,减小输出文件体积
    "removeComments": false,
    
    // 指定输出目录
    "outDir": "./dist"
  },
  
  // 指定要包含在编译中的文件或目录
  "include": [
    "src/**/*"
  ],
  
  // 指定要排除在编译之外的文件或目录
  "exclude": [
    "node_modules",
    "dist"
  ]
}

4,项目构建工具

这个项目使用了多种构建工具的组合,主要包括:

  1. Turborepo (turbo) :作为 monorepo 的任务编排工具,负责协调各个包的构建、测试等任务。从根目录的 package.json 中可以看到大量使用了 turbo run 命令。

  2. tsup :作为实际的 TypeScript 构建工具,用于将 TypeScript 代码编译为 JavaScript。这是一个基于 esbuild 的高性能构建工具,适合库的打包。

  3. unbuild :某些包可能使用了 unbuild 作为构建工具,它提供了更多的配置选项。

项目的构建流程大致是:

  • Turborepo 负责调度和并行执行各个包的构建任务

  • 各个包内部使用 tsup 或 unbuild 进行实际的代码编译和打包

  • TypeScript 编译器 (tsc) 主要用于类型检查,而不是实际的代码生成

从 tsconfig.json 的配置来看,项目使用了现代的 ESM 模块系统和打包工具,这与 tsup 的定位相符。

5,解构赋值 类型注解

解构赋值 是 JavaScript 的语言特性,ECMAScript 6 (ES6) 引入的,所有现代 JavaScript 环境都支持,包括 Node.js。类型注解 是 TypeScript 特有的,用于静态类型检查

这种类型注解方式是 TypeScript 特有的,在编译后会被移除,不会影响运行时的 JavaScript 代码。

typescript高级写法:

TypeScript 中的一种高级参数模式

undefined
async buildPackage(
    { dep, outDir, options, isDependenciesCacheOutdate, heading = '', subPackage }:
      { dep: string, outDir: string, options?: TsupOptions, isDependenciesCacheOutdate: boolean, heading: string, subPackage?: SubPackage },
  ) {

它有以下优点:

  • 参数顺序不重要,调用时通过属性名指定

  • 可以轻松添加或移除参数而不破坏现有代码

  • 函数调用时参数的用途更加清晰

  • 类型安全,编译器会检查参数类型