Skip to content

TypeScript 基本结构

TypeScript 程序的基本结构与 JavaScript 类似,但添加了一些额外的组织方式,如模块、命名空间、接口和类等。本文将介绍 TypeScript 程序的基本结构。

1. 基本组成

一个 TypeScript 程序通常由以下部分组成:

  • 导入语句:用于导入其他模块或库
  • 变量声明:声明变量和常量
  • 函数声明:定义函数
  • 类声明:定义类
  • 接口声明:定义接口
  • 命名空间声明:定义命名空间
  • 导出语句:用于导出模块成员
  • 执行代码:程序的主要逻辑

2. 简单的 TypeScript 程序

以下是一个简单的 TypeScript 程序示例:

typescript
// 导入语句
import * as fs from 'fs';

// 变量声明
const message: string = "Hello, TypeScript!";

// 函数声明
function greet(name: string): string {
  return `Hello, ${name}!`;
}

// 类声明
class Person {
  private name: string;
  private age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  public greet(): string {
    return `Hello, my name is ${this.name} and I am ${this.age} years old.`;
  }
}

// 接口声明
interface Animal {
  name: string;
  makeSound(): void;
}

// 命名空间声明
namespace MathUtils {
  export function add(a: number, b: number): number {
    return a + b;
  }

  export function subtract(a: number, b: number): number {
    return a - b;
  }
}

// 导出语句
export { Person, Animal, MathUtils };

// 执行代码
console.log(message);
console.log(greet("John"));

const person = new Person("John", 30);
console.log(person.greet());

console.log(MathUtils.add(1, 2));

3. 入口点

在 TypeScript 中,程序的入口点通常是一个包含 main 函数或直接执行代码的文件。当你编译并运行 TypeScript 程序时,编译器会从入口点开始执行。

示例:带有 main 函数的程序

typescript
// app.ts
function main(): void {
  console.log("Hello, TypeScript!");
  // 程序的主要逻辑
}

// 调用 main 函数
main();

示例:直接执行的程序

typescript
// app.ts
console.log("Hello, TypeScript!");

// 直接执行的代码
const name: string = "John";
console.log(`Hello, ${name}!`);

4. 模块结构

TypeScript 支持 ES 模块系统,使用 importexport 语句来组织代码。模块是代码组织的基本单位,每个模块都有自己的作用域。

模块的基本结构

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

export function subtract(a: number, b: number): number {
  return a - b;
}

// 导出常量
export const PI: number = 3.14159;

// 导出类型
export interface Point {
  x: number;
  y: number;
}

// app.ts
// 导入模块成员
import { add, subtract, PI, Point } from "./math";

// 使用导入的成员
console.log(add(1, 2)); // 3
console.log(subtract(5, 3)); // 2
console.log(PI); // 3.14159

const point: Point = { x: 10, y: 20 };
console.log(point); // { x: 10, y: 20 }

默认导出

模块可以有一个默认导出,使用 export default 语法:

typescript
// math.ts
export default function multiply(a: number, b: number): number {
  return a * b;
}

// app.ts
import multiply from "./math";
console.log(multiply(2, 3)); // 6

导入所有成员

可以使用 * as 语法导入模块的所有成员:

typescript
// app.ts
import * as MathUtils from "./math";

console.log(MathUtils.add(1, 2)); // 3
console.log(MathUtils.subtract(5, 3)); // 2
console.log(MathUtils.PI); // 3.14159

5. 命名空间

命名空间是 TypeScript 中另一种组织代码的方式,它允许你将相关的代码组织在一起,避免命名冲突。

命名空间的基本结构

typescript
// utils.ts
namespace Utils {
  export function formatDate(date: Date): string {
    return date.toISOString();
  }

  export function formatCurrency(amount: number): string {
    return `$${amount.toFixed(2)}`;
  }
}

// app.ts
// 使用命名空间中的函数
console.log(Utils.formatDate(new Date()));
console.log(Utils.formatCurrency(100));

嵌套命名空间

命名空间可以嵌套,以创建更复杂的代码组织:

typescript
// utils.ts
namespace Utils {
  export namespace DateUtils {
    export function formatDate(date: Date): string {
      return date.toISOString();
    }

    export function parseDate(dateString: string): Date {
      return new Date(dateString);
    }
  }

  export namespace CurrencyUtils {
    export function formatCurrency(amount: number): string {
      return `$${amount.toFixed(2)}`;
    }

    export function parseCurrency(currencyString: string): number {
      return parseFloat(currencyString.replace('$', ''));
    }
  }
}

// app.ts
console.log(Utils.DateUtils.formatDate(new Date()));
console.log(Utils.CurrencyUtils.formatCurrency(100));

6. 类和接口的组织

在 TypeScript 中,类和接口是组织代码的重要方式。它们可以帮助你创建更结构化、更可维护的代码。

类的基本结构

typescript
// person.ts
export class Person {
  private name: string;
  private age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  public getName(): string {
    return this.name;
  }

  public getAge(): number {
    return this.age;
  }

  public setName(name: string): void {
    this.name = name;
  }

  public setAge(age: number): void {
    this.age = age;
  }

  public greet(): string {
    return `Hello, my name is ${this.name} and I am ${this.age} years old.`;
  }
}

// app.ts
import { Person } from "./person";

const person = new Person("John", 30);
console.log(person.greet()); // Hello, my name is John and I am 30 years old.

person.setName("Jane");
person.setAge(25);
console.log(person.greet()); // Hello, my name is Jane and I am 25 years old.

接口的基本结构

typescript
// animal.ts
export interface Animal {
  name: string;
  makeSound(): void;
}

export class Dog implements Animal {
  public name: string;

  constructor(name: string) {
    this.name = name;
  }

  public makeSound(): void {
    console.log("Woof! Woof!");
  }
}

export class Cat implements Animal {
  public name: string;

  constructor(name: string) {
    this.name = name;
  }

  public makeSound(): void {
    console.log("Meow! Meow!");
  }
}

// app.ts
import { Animal, Dog, Cat } from "./animal";

function letAnimalSpeak(animal: Animal): void {
  console.log(`${animal.name} says:`);
  animal.makeSound();
}

const dog = new Dog("Buddy");
const cat = new Cat("Whiskers");

letAnimalSpeak(dog); // Buddy says: Woof! Woof!
letAnimalSpeak(cat); // Whiskers says: Meow! Meow!

7. 代码组织最佳实践

1. 使用模块组织代码

将相关的代码组织到模块中,每个模块负责一个特定的功能。

src/
  ├── utils/
  │   ├── math.ts
  │   ├── date.ts
  │   └── index.ts
  ├── models/
  │   ├── person.ts
  │   ├── animal.ts
  │   └── index.ts
  ├── services/
  │   ├── userService.ts
  │   ├── productService.ts
  │   └── index.ts
  ├── components/
  │   ├── button.ts
  │   ├── input.ts
  │   └── index.ts
  ├── app.ts
  └── index.ts

2. 使用接口定义类型

使用接口定义数据结构和类型,提高代码的可读性和可维护性。

typescript
// 定义用户接口
interface User {
  id: number;
  name: string;
  email: string;
  age?: number;
}

// 使用接口
function getUser(id: number): User {
  return {
    id,
    name: "John",
    email: "john@example.com"
  };
}

3. 使用类封装逻辑

使用类封装相关的属性和方法,提高代码的组织性和可重用性。

typescript
class UserService {
  private users: User[] = [];

  public addUser(user: User): void {
    this.users.push(user);
  }

  public getUser(id: number): User | undefined {
    return this.users.find(user => user.id === id);
  }

  public updateUser(id: number, updates: Partial<User>): void {
    const index = this.users.findIndex(user => user.id === id);
    if (index !== -1) {
      this.users[index] = { ...this.users[index], ...updates };
    }
  }

  public deleteUser(id: number): void {
    this.users = this.users.filter(user => user.id !== id);
  }
}

4. 使用命名空间组织相关代码

使用命名空间组织相关的代码,避免命名冲突。

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

  export function validatePassword(password: string): boolean {
    return password.length >= 8;
  }
}

// 使用命名空间中的函数
console.log(Validation.validateEmail("john@example.com")); // true
console.log(Validation.validatePassword("password123")); // true

5. 使用类型别名简化复杂类型

使用类型别名简化复杂的类型定义,提高代码的可读性。

typescript
type UserId = number;
type UserName = string;
type Email = string;

type User = {
  id: UserId;
  name: UserName;
  email: Email;
  age?: number;
};

function getUser(id: UserId): User {
  return {
    id,
    name: "John",
    email: "john@example.com"
  };
}

8. 项目结构示例

小型项目结构

my-app/
  ├── src/
  │   ├── utils.ts
  │   ├── models.ts
  │   ├── app.ts
  │   └── index.ts
  ├── package.json
  ├── tsconfig.json
  └── README.md

中型项目结构

my-app/
  ├── src/
  │   ├── utils/
  │   │   ├── math.ts
  │   │   ├── date.ts
  │   │   └── index.ts
  │   ├── models/
  │   │   ├── user.ts
  │   │   ├── product.ts
  │   │   └── index.ts
  │   ├── services/
  │   │   ├── userService.ts
  │   │   ├── productService.ts
  │   │   └── index.ts
  │   ├── components/
  │   │   ├── button.tsx
  │   │   ├── input.tsx
  │   │   └── index.ts
  │   ├── pages/
  │   │   ├── home.tsx
  │   │   ├── about.tsx
  │   │   └── index.ts
  │   ├── app.tsx
  │   └── index.tsx
  ├── public/
  │   ├── index.html
  │   └── favicon.ico
  ├── package.json
  ├── tsconfig.json
  ├── webpack.config.js
  └── README.md

9. 编译和运行 TypeScript 程序

编译 TypeScript 文件

使用 tsc 命令编译 TypeScript 文件:

bash
tsc app.ts

这会生成一个 app.js 文件,然后你可以使用 node 命令运行它:

bash
node app.js

使用 tsconfig.json

创建一个 tsconfig.json 文件来配置编译选项:

json
{
  "compilerOptions": {
    "target": "es2016",
    "module": "commonjs",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true,
    "outDir": "./dist"
  },
  "include": ["./src/**/*"]
}

然后运行 tsc 命令编译整个项目:

bash
tsc

这会将编译后的文件输出到 dist 目录中。

总结

TypeScript 程序的基本结构包括:

  • 基本组成:导入语句、变量声明、函数声明、类声明、接口声明、命名空间声明、导出语句和执行代码
  • 入口点:程序的起始执行点
  • 模块结构:使用 ES 模块系统组织代码
  • 命名空间:用于组织相关代码,避免命名冲突
  • 类和接口:用于创建结构化、可维护的代码
  • 代码组织最佳实践:使用模块、接口、类和命名空间组织代码
  • 项目结构:根据项目大小和复杂度组织文件结构

通过合理组织 TypeScript 代码,你可以创建更结构化、更可维护、更易于理解的程序。