【TS入门笔记5--- 项目构成】

TS入门笔记5

  • TypeScript--- 项目构成
  • 一、项目基础结构概述
      • 1. 一个典型的 TypeScript 项目通常有以下基本的文件和目录结构
      • 2.各部分说明
  • 二、编译上下文
      • 1. 概念
      • 2.include属性
      • 3. exclude属性
      • 4. files 属性
  • 三、声明空间
      • 1. 类型声明空间
      • 2.值声明空间
  • 四、模块
      • 1.模块的导出
      • 2.模块的导入
      • 3.模块解析策略
  • 五、命名空间
      • 1.命名空间的定义和使用
      • 2. 命名空间的嵌套
      • 3. 命名空间与模块的区别
  • 六、动态导入表达式
      • 1.概念
      • 2.语法
      • 3.异步使用
      • 4.应用场景

TypeScript— 项目构成

一、项目基础结构概述

1. 一个典型的 TypeScript 项目通常有以下基本的文件和目录结构

project-root/
├── src/
│   ├── components/
│   │   ├── Button.tsx
│   │   └── Input.tsx
│   ├── pages/
│   │   ├── HomePage.tsx
│   │   └── AboutPage.tsx
│   ├── utils/
│   │   ├── api.ts
│   │   └── format.ts
│   ├── index.ts
│   └── global.d.ts
├── tests/
│   ├── unit/
│   │   ├── Button.test.ts
│   │   └── api.test.ts
│   └── integration/
│       └── HomePage.test.ts
├── dist/
├── node_modules/
├── package.json
├── tsconfig.json
├── .gitignore
└── README.md

2.各部分说明

(1)src 目录:存放项目的源代码,是开发的核心区域。
(2)tests 目录:包含单元测试和集成测试的代码,用于保证代码的质量和功能正确性。
(3)dist 目录:编译后的 JavaScript 文件会输出到这里,用于部署到生产环境。
(4)node_modules 目录:项目依赖的第三方库会安装在此目录下。
(5)package.json:记录项目的元数据、依赖信息以及脚本命令等。
(6)tsconfig.json:TypeScript 编译器的配置文件,决定了编译的行为和规则。
(7)gitignore:指定哪些文件和目录不需要被纳入版本控制。
(8)README.md:项目的说明文档,介绍项目的基本信息、使用方法等。

二、编译上下文

1. 概念

编译上下文指的是 TypeScript 编译器在编译过程中所考虑的一组文件。编译器会根据 tsconfig.json 中的配置来确定哪些文件属于编译上下文。
【TS入门笔记5--- 项目构成】_第1张图片

2.include属性

include 指定了需要包含在编译上下文中的文件或目录路径。例如:

{
    "compilerOptions": {
        "target": "ES6",
        "module": "commonjs"
    },
    "include": ["src/**/*.ts"]
}

上述配置表示将 src 目录下的所有 .ts 文件纳入编译上下文。

3. exclude属性

exclude 则指定了需要从编译上下文中排除的文件或目录路径。例如:

{
    "compilerOptions": {
        "target": "ES6",
        "module": "commonjs"
    },
    "include": ["src/**/*.ts"],
    "exclude": ["src/tests/**/*.ts"]
}

这样就会把 src/tests 目录下的 .ts 文件排除在编译上下文之外。

4. files 属性

files 用于精确指定需要包含在编译上下文中的文件列表。例如:

{
    "compilerOptions": {
        "target": "ES6",
        "module": "commonjs"
    },
    "files": ["src/index.ts", "src/utils/api.ts"]
}

只有 src/index.ts 和 src/utils/api.ts 这两个文件会被纳入编译上下文。

三、声明空间

1. 类型声明空间

类型声明空间用于定义类型相关的内容,如接口、类型别名、枚举等。这些声明只能用于类型注解和类型检查,不能作为值来使用。

// 接口声明
interface User {
    name: string;
    age: number;
}

// 类型别名声明
type Point = {
    x: number;
    y: number;
};

// 枚举声明
enum Color {
    Red,
    Green,
    Blue
}

// 使用类型声明
const user: User = { name: 'John', age: 30 };

2.值声明空间

值声明空间用于定义可以在运行时使用的值,如变量、函数、类等。

// 变量声明
let num = 10;

// 函数声明
function add(a: number, b: number): number {
    return a + b;
}

// 类声明
class Person {
    constructor(public name: string) {}
    sayHello() {
        console.log(`Hello, my name is ${this.name}`);
    }
}

// 使用值声明
const result = add(1, 2);
const person = new Person('Alice');
person.sayHello();

类型和值声明空间的区别:类型声明空间中的声明只能用于类型相关的操作,而值声明空间中的声明可以在运行时被调用或使用。例如,不能将接口作为值来传递或调用。

四、模块

在 TypeScript 中,模块是一种将代码组织成独立单元的方式,每个模块都有自己的作用域,模块之间可以通过 import 和 export 关键字进行通信。

1.模块的导出

(1)命名导出:可以导出多个变量、函数、类等,通过名称来引用。

// math.ts
export function add(a: number, b: number) {
    return a + b;
}

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

(2)默认导出:每个模块只能有一个默认导出,使用 export default 关键字。

// person.ts
class Person {
    constructor(public name: string) {}
    sayHello() {
        console.log(`Hello, my name is ${this.name}`);
    }
}

export default Person;

2.模块的导入

(1)导入命名导出

// main.ts
import { add, subtract } from './math';

const sum = add(1, 2);
const diff = subtract(5, 3);

(2)导入默认导出

// app.ts
import Person from './person';

const person = new Person('Bob');
person.sayHello();

3.模块解析策略

相对路径解析:使用相对路径来指定模块的位置,如 import { add } from ‘./math’;。
非相对路径解析:根据 tsconfig.json 中的 baseUrl 和 paths 配置来解析模块。例如:

{
    "compilerOptions": {
        "baseUrl": ".",
        "paths": {
            "@utils/*": ["src/utils/*"]
        }
    }
}
import { apiCall } from '@utils/api';

五、命名空间

命名空间(以前也称为内部模块)是一种在全局作用域中组织代码的方式,用于避免命名冲突。

1.命名空间的定义和使用

// shapes.ts
namespace Shapes {
    export class Circle {
        constructor(private radius: number) {}
        getArea() {
            return Math.PI * this.radius * this.radius;
        }
    }

    export class Square {
        constructor(private sideLength: number) {}
        getArea() {
            return this.sideLength * this.sideLength;
        }
    }
}

// 使用命名空间
const circle = new Shapes.Circle(5);
const square = new Shapes.Square(4);

console.log(circle.getArea());
console.log(square.getArea());

2. 命名空间的嵌套

命名空间可以嵌套使用,以进一步组织代码。

namespace Geometry {
    export namespace Shapes {
        export class Triangle {
            constructor(private base: number, private height: number) {}
            getArea() {
                return 0.5 * this.base * this.height;
            }
        }
    }
}

const triangle = new Geometry.Shapes.Triangle(3, 4);
console.log(triangle.getArea());

3. 命名空间与模块的区别

作用域:命名空间在全局作用域中定义,而模块有自己独立的作用域。
使用场景:命名空间适用于在一个文件中组织相关的代码,避免全局命名冲突;模块更适合于大型项目,将代码拆分成多个独立的文件进行管理。

六、动态导入表达式

1.概念

动态导入表达式允许在运行时动态地加载模块,而不是在编译时静态地导入。这在需要按需加载模块的场景中非常有用,例如懒加载路由组件。

2.语法

// 动态导入模块
const module = import('./math');

module.then((math) => {
    const sum = math.add(1, 2);
    console.log(sum);
});

3.异步使用

动态导入返回一个 Promise,因此可以使用 async/await 来处理。

async function loadModule() {
    const math = await import('./math');
    const diff = math.subtract(5, 3);
    console.log(diff);
}

loadModule();

4.应用场景

(1)懒加载组件:在单页面应用中,当用户访问某个路由时再动态加载对应的组件,提高应用的加载性能。

// 路由配置
const routes = [
    {
        path: '/home',
        component: () => import('./HomePage')
    },
    {
        path: '/about',
        component: () => import('./AboutPage')
    }
];

(2)按需加载功能模块:根据用户的操作或特定条件,动态加载所需的功能模块。

你可能感兴趣的:(笔记,typescript)