Skip to content

TypeScript 模块化与工程化

模块化是现代前端开发的重要组成部分,TypeScript 支持多种模块系统,本章节将介绍 TypeScript 中的模块化和工程化实践。

导出 export

在 TypeScript 中,使用 export 关键字导出模块中的内容。

导出变量和函数

示例:

typescript
// utils.ts
// 导出变量
export const PI = 3.14159;

// 导出函数
export function add(a: number, b: number): number {
  return a + b;
}

export function multiply(a: number, b: number): number {
  return a * b;
}

// 导出类型
export type User = {
  id: number;
  name: string;
  email: string;
};

导出默认值

示例:

typescript
// math.ts
// 导出默认值
export default {
  add(a: number, b: number): number {
    return a + b;
  },
  multiply(a: number, b: number): number {
    return a * b;
  }
};

导出并重命名

示例:

typescript
// utils.ts
const PI = 3.14159;
function add(a: number, b: number): number {
  return a + b;
}

// 导出并重命名
export { PI as CONSTANT_PI, add as sum };

导入 import

在 TypeScript 中,使用 import 关键字导入模块中的内容。

导入指定内容

示例:

typescript
// app.ts
// 导入指定内容
import { PI, add, multiply, User } from './utils';

console.log(PI); // 3.14159
console.log(add(1, 2)); // 3
console.log(multiply(2, 3)); // 6

const user: User = {
  id: 1,
  name: "John",
  email: "john@example.com"
};

导入默认值

示例:

typescript
// app.ts
// 导入默认值
import math from './math';

console.log(math.add(1, 2)); // 3
console.log(math.multiply(2, 3)); // 6

导入并重命名

示例:

typescript
// app.ts
// 导入并重命名
import { PI as CONSTANT_PI, add as sum } from './utils';

console.log(CONSTANT_PI); // 3.14159
console.log(sum(1, 2)); // 3

导入所有内容

示例:

typescript
// app.ts
// 导入所有内容
import * as utils from './utils';

console.log(utils.PI); // 3.14159
console.log(utils.add(1, 2)); // 3
console.log(utils.multiply(2, 3)); // 6

类型导出与导入

TypeScript 支持单独导出和导入类型。

导出类型

示例:

typescript
// types.ts
// 导出接口
export interface User {
  id: number;
  name: string;
  email: string;
}

// 导出类型别名
export type Status = "active" | "inactive" | "pending";

// 导出枚举
export enum Role {
  Admin = "admin",
  User = "user",
  Guest = "guest"
}

导入类型

示例:

typescript
// app.ts
// 导入类型
import { User, Status, Role } from './types';

const user: User = {
  id: 1,
  name: "John",
  email: "john@example.com"
};

const status: Status = "active";
const role: Role = Role.Admin;

// 使用 import type 导入类型(TypeScript 3.8+)
import type { User as UserType } from './types';

const user2: UserType = {
  id: 2,
  name: "Jane",
  email: "jane@example.com"
};

声明文件 .d.ts 是什么

声明文件(.d.ts)是 TypeScript 中用于声明类型的文件,它不包含实际的代码实现,只包含类型声明。

声明文件的作用

  1. 为 JavaScript 库提供类型定义:使 TypeScript 能够理解 JavaScript 库的类型
  2. 为项目中的模块提供类型声明:提高代码的类型安全性
  3. 避免重复类型定义:将类型定义集中管理

声明文件示例

示例:

typescript
// types.d.ts
// 声明全局变量
declare const PI: number;

// 声明全局函数
declare function greet(name: string): string;

// 声明接口
declare interface User {
  id: number;
  name: string;
  email: string;
}

// 声明命名空间
declare namespace Utils {
  function add(a: number, b: number): number;
  function multiply(a: number, b: number): number;
}

为第三方库写类型

当使用没有类型定义的第三方库时,你可以为其创建声明文件。

示例:为 jQuery 创建声明文件

typescript
// jquery.d.ts
declare namespace jQuery {
  interface JQuery {
    css(property: string, value: string): JQuery;
    html(html: string): JQuery;
    on(event: string, handler: () => void): JQuery;
    // 其他方法...
  }
}

declare function $(
  selector: string
): jQuery.JQuery;

declare module "jquery" {
  export = $;
}

使用第三方库的类型定义

  1. 使用 @types 包:许多流行的库都有对应的 @types 包,例如:

    bash
    npm install --save-dev @types/jquery
  2. 在 tsconfig.json 中配置类型根目录

    json
    {
      "compilerOptions": {
        "typeRoots": ["node_modules/@types", "src/types"]
      }
    }

TS + Vite 项目创建

Vite 是一个现代前端构建工具,它对 TypeScript 有很好的支持。

步骤 1:创建 Vite 项目

bash
# 使用 npm
npm create vite@latest my-project -- --template typescript

# 使用 yarn
yarn create vite my-project --template typescript

# 使用 pnpm
pnpm create vite my-project --template typescript

步骤 2:安装依赖

bash
cd my-project
npm install

步骤 3:运行开发服务器

bash
npm run dev

步骤 4:构建项目

bash
npm run build

TS + Vue/React 基础使用

TypeScript + Vue

创建 Vue + TypeScript 项目

bash
# 使用 npm
npm create vite@latest my-vue-project -- --template vue-ts

# 使用 yarn
yarn create vite my-vue-project --template vue-ts

# 使用 pnpm
pnpm create vite my-vue-project --template vue-ts

Vue 组件中的 TypeScript

vue
<!-- App.vue -->
<template>
  <div>
    <h1>{{ message }}</h1>
    <button @click="increment">Count: {{ count }}</button>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';

// 类型注解
const message: string = 'Hello TypeScript';
const count = ref<number>(0);

// 函数类型
function increment(): void {
  count.value++;
}
</script>

TypeScript + React

创建 React + TypeScript 项目

bash
# 使用 npm
npm create vite@latest my-react-project -- --template react-ts

# 使用 yarn
yarn create vite my-react-project --template react-ts

# 使用 pnpm
pnpm create vite my-react-project --template react-ts

React 组件中的 TypeScript

tsx
// App.tsx
import React, { useState } from 'react';

// 类型定义
interface Props {
  title: string;
}

const App: React.FC<Props> = ({ title }) => {
  // 状态类型
  const [count, setCount] = useState<number>(0);

  // 函数类型
  const increment = (): void => {
    setCount(count + 1);
  };

  return (
    <div>
      <h1>{title}</h1>
      <button onClick={increment}>Count: {count}</button>
    </div>
  );
};

export default App;

实战:TypeScript 模块化项目

示例:创建一个模块化的 TypeScript 项目

步骤 1:创建项目结构

src/
├── components/
│   ├── Button.tsx
│   └── Card.tsx
├── hooks/
│   └── useCounter.ts
├── types/
│   └── index.ts
├── utils/
│   └── index.ts
├── App.tsx
└── main.tsx

步骤 2:创建类型定义

typescript
// src/types/index.ts
export interface User {
  id: number;
  name: string;
  email: string;
}

export type Status = "active" | "inactive" | "pending";

步骤 3:创建工具函数

typescript
// src/utils/index.ts
export function formatDate(date: Date): string {
  return date.toISOString().split('T')[0];
}

export function validateEmail(email: string): boolean {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}

步骤 4:创建自定义 Hook

typescript
// src/hooks/useCounter.ts
import { useState, useCallback } from 'react';

export function useCounter(initialValue: number = 0) {
  const [count, setCount] = useState<number>(initialValue);

  const increment = useCallback(() => setCount(c => c + 1), []);
  const decrement = useCallback(() => setCount(c => c - 1), []);
  const reset = useCallback(() => setCount(initialValue), [initialValue]);

  return { count, increment, decrement, reset };
}

步骤 5:创建组件

tsx
// src/components/Button.tsx
import React from 'react';

interface ButtonProps {
  children: React.ReactNode;
  onClick: () => void;
  variant?: 'primary' | 'secondary';
  disabled?: boolean;
}

const Button: React.FC<ButtonProps> = ({
  children,
  onClick,
  variant = 'primary',
  disabled = false
}) => {
  return (
    <button
      onClick={onClick}
      disabled={disabled}
      style={{
        padding: '8px 16px',
        border: 'none',
        borderRadius: '4px',
        backgroundColor: variant === 'primary' ? '#007bff' : '#6c757d',
        color: 'white',
        cursor: disabled ? 'not-allowed' : 'pointer'
      }}
    >
      {children}
    </button>
  );
};

export default Button;
tsx
// src/components/Card.tsx
import React from 'react';

interface CardProps {
  title: string;
  children: React.ReactNode;
  className?: string;
}

const Card: React.FC<CardProps> = ({ title, children, className = '' }) => {
  return (
    <div
      style={{
        border: '1px solid #e0e0e0',
        borderRadius: '8px',
        padding: '16px',
        margin: '16px 0',
        boxShadow: '0 2px 4px rgba(0, 0, 0, 0.1)'
      }}
      className={className}
    >
      <h3 style={{ margin: '0 0 12px 0' }}>{title}</h3>
      {children}
    </div>
  );
};

export default Card;

步骤 6:创建 App 组件

tsx
// src/App.tsx
import React from 'react';
import Button from './components/Button';
import Card from './components/Card';
import { useCounter } from './hooks/useCounter';
import { formatDate } from './utils';

const App: React.FC = () => {
  const { count, increment, decrement, reset } = useCounter(0);

  return (
    <div style={{ maxWidth: '600px', margin: '0 auto', padding: '20px' }}>
      <h1>TypeScript + React Example</h1>
      
      <Card title="Counter">
        <p>Count: {count}</p>
        <div style={{ display: 'flex', gap: '8px' }}>
          <Button onClick={increment}>Increment</Button>
          <Button onClick={decrement}>Decrement</Button>
          <Button onClick={reset} variant="secondary">Reset</Button>
        </div>
      </Card>

      <Card title="Date">
        <p>Today: {formatDate(new Date())}</p>
      </Card>
    </div>
  );
};

export default App;

步骤 7:创建入口文件

tsx
// src/main.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

小结

本章节介绍了 TypeScript 中的模块化和工程化实践,包括:

  • 导出 export:导出变量、函数、类型
  • 导入 import:导入指定内容、默认值、并重命名
  • 类型导出与导入:单独导出和导入类型
  • 声明文件 .d.ts:为 JavaScript 库提供类型定义
  • 为第三方库写类型:创建自定义声明文件
  • TS + Vite 项目创建:使用 Vite 搭建 TypeScript 项目
  • TS + Vue/React 基础使用:在 Vue 和 React 中使用 TypeScript
  • 实战:创建一个模块化的 TypeScript 项目

模块化和工程化是现代前端开发的重要组成部分,通过合理的模块划分和类型定义,可以提高代码的可维护性和可重用性。在实际开发中,应该根据项目的具体需求,选择合适的模块系统和工程化工具,以提高开发效率和代码质量。

© 2026 编程马·菜鸟教程 版权所有