Appearance
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 中用于声明类型的文件,它不包含实际的代码实现,只包含类型声明。
声明文件的作用
- 为 JavaScript 库提供类型定义:使 TypeScript 能够理解 JavaScript 库的类型
- 为项目中的模块提供类型声明:提高代码的类型安全性
- 避免重复类型定义:将类型定义集中管理
声明文件示例
示例:
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 = $;
}使用第三方库的类型定义
使用 @types 包:许多流行的库都有对应的 @types 包,例如:
bashnpm install --save-dev @types/jquery在 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 buildTS + 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-tsVue 组件中的 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-tsReact 组件中的 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 项目
模块化和工程化是现代前端开发的重要组成部分,通过合理的模块划分和类型定义,可以提高代码的可维护性和可重用性。在实际开发中,应该根据项目的具体需求,选择合适的模块系统和工程化工具,以提高开发效率和代码质量。
