TypeScript 与后端开辟Node.js

打印 上一主题 下一主题

主题 807|帖子 807|积分 2421

文章目次



  • 一、搭建 TypeScript + Node.js 项目


    • (一)初始化项目并安装相干依赖


      • 1、创建项目目次并初始化
      • 2、安装必要的依赖包

    • (二)配置 TypeScript 编译选项(如模块剖析方式适合后端)

  • 二、编写服务器代码


    • (一)界说路由类型(使用 Express 等框架)
    • (二)处理请求和响应的类型(包括中间件的类型)


      • 1、请求类型处理
      • 2、响应类型处理
      • 3、中间件类型处理


  • 三、数据库交互


    • (一)使用 Type - Safe 的数据库驱动(如 TypeORM)


      • 1、安装 TypeORM 及相干依赖
      • 2、配置数据库连接

    • (二)界说数据库模型和操作的类型(增编削查)


      • 1、界说数据库模型(实体类)
      • 2、数据库操作的类型安全实现(增编削查)




一、搭建 TypeScript + Node.js 项目

(一)初始化项目并安装相干依赖

1、创建项目目次并初始化

首先,创建一个新的项目文件夹,例如通过下令行操作:
  1. mkdir my-node-ts-project
  2. cd my-node-ts-project
  3. npm init -y
复制代码
npm init -y 下令会初始化一个 package.json 文件,用于管理项目的依赖和相干配置信息,-y 参数表现使用默认配置进行初始化。
2、安装必要的依赖包

对于一个基于 TypeScript 和 Node.js 的后端项目,需要安装以下核心依赖:


  • typescript:TypeScript 编译器,用于将 TypeScript 代码编译为 JavaScript 代码。可以通过以下下令安装:
    npm install typescript --save-dev
这里使用 --save-dev 表现将其作为开辟依赖安装,由于它重要在开辟阶段使用,项目运行时并不直接依赖它。


  • @types/node:这个包提供了 Node.js 相干的类型界说,使得在 TypeScript 代码中使用 Node.js 的内置模块(如 http、fs 等)时能够有类型检查和智能提示等功能,安装下令如下:
    npm install @types/node --save-dev
另外,如果计划使用一些特定的后端框架(如 Express),还需要安装对应的依赖包以及相应的类型界说包(如 @types/express)。例如安装 Express:
  1. npm install express
  2. npm install @types/express --save-dev
复制代码
(二)配置 TypeScript 编译选项(如模块剖析方式适合后端)

在项目根目次下创建 tsconfig.json 文件,用于配置 TypeScript 的编译选项。以下是一个适合后端开辟的根本配置示例:
  1. {
  2.   "compilerOptions": {
  3.     "target": "es6",
  4.     "module": "commonjs",
  5.     "outDir": "dist",
  6.     "rootDir": "src",
  7.     "strict": true,
  8.     "esModuleInterop": true,
  9.     "sourceMap": true,
  10.     "resolveJsonModule": true
  11.   },
  12.   "include": ["src/**/*.ts"],
  13.   "exclude": ["node_modules"]
  14. }
复制代码
解释一下关键配置项:


  • target:指定将 TypeScript 代码编译成的 JavaScript 版本,这里选择 es6,可以利用一些较新的 JavaScript 特性,同时在大多数 Node.js 情况中也能很好地支持。
  • module:设置模块系统,commonjs 是 Node.js 常用的模块规范,便于在后端情况中进行模块的导入和导出操作。
  • outDir:界说编译后 JavaScript 文件的输出目次,这里设置为 dist,意味着编译后的 .js 文件会存放在 dist 文件夹下。
  • rootDir:指定 TypeScript 源代码的根目次,通常是 src 文件夹,编译器会从这个目次及其子目次中查找 .ts 文件进行编译。
  • strict:开启严格模式,启用全面的类型检查等功能,有助于提高代码质量,减少潜伏错误。
  • esModuleInterop:办理在 CommonJS 和 ES 模块之间互操作时可能出现的一些题目,方便在项目中同时使用差别模块规范引入的依赖。
  • sourceMap:生成源映射文件(.map 文件),在调试时能够将编译后的 JavaScript 代码映射回原始的 TypeScript 代码,方便查找题目。
  • resolveJsonModule:答应在 TypeScript 中直接导入 .json 文件,并将其剖析为相应的 JavaScript 对象,这在后端项目中处理配置文件等情况时很有用。
二、编写服务器代码

(一)界说路由类型(使用 Express 等框架)

以 Express 框架为例,在 TypeScript 中界说路由时,可以先创建一个路由模块,然后明确路由处理函数的类型。
例如,创建一个简单的 userRoutes.ts 文件用于界说用户相干的路由:
  1. import express from 'express';
  2. import { Request, Response } from 'express';
  3. const router = express.Router();
  4. // 定义一个获取用户信息的路由
  5. router.get('/users/:id', (req: Request, res: Response) => {
  6.   const userId = req.params.id;
  7.   // 这里可以假设从数据库等地方获取用户信息并返回,暂时模拟返回一个固定信息
  8.   const user = { id: userId, name: 'John Doe' };
  9.   res.json(user);
  10. });
  11. export default router;
复制代码
在上述代码中:


  • 首先导入了 express 框架以及 express 中的 Request 和 Response 类型界说,它们分别用于形貌 HTTP 请求和响应的相干结构和属性类型。
  • 然后使用 express.Router() 创建了一个路由实例 router,并界说了一个 GET 类型的路由 /users/:id,其处理函数吸收 Request 和 Response 类型的参数,在函数内部可以通过 req.params 获取路由参数(这里是用户 ID),并根据业务逻辑返回相应的用户信息(这里简单地返回了模拟数据,实际中可能会从数据库查询等操作获取真实数据),最后通过 res.json() 方法将数据以 JSON 格式返回给客户端。
(二)处理请求和响应的类型(包括中间件的类型)

1、请求类型处理

除了根本的路由参数获取,请求对象(Request)还包罗很多其他属性,好比请求头(headers)、请求体(body)等,在 TypeScript 中可以对它们进行相应的类型界说和处理。
例如,创建一个吸收用户注册信息的路由,需要处理请求体中的 JSON 数据(假设用户注册信息包罗用户名和密码):
  1. import express from 'express';
  2. import { Request, Response } from 'express';
  3. interface UserRegistration {
  4.   username: string;
  5.   password: string;
  6. }
  7. const router = express.Router();
  8. router.post('/register', (req: Request<{}, {}, UserRegistration>, res: Response) => {
  9.   const userData: UserRegistration = req.body;
  10.   console.log(`Received registration data: ${JSON.stringify(userData)}`);
  11.   // 这里可以进行后续的业务逻辑,比如将用户信息存入数据库等操作
  12.   res.status(201).send('Registration successful');
  13. });
  14. export default router;
复制代码
在这个示例中,界说了 UserRegistration 接口来形貌用户注册信息的结构(包罗用户名和密码两个属性,类型都为 string),在路由处理函数的 Request 类型参数中,通过泛型指定了请求体的类型为 UserRegistration,这样在函数内部就能安全地从 req.body 获取并使用用户注册信息了,编译器会确保类型的一致性。
2、响应类型处理

对于响应对象(Response),可以根据差别的业务需求设置响应状态码、响应头以及返回差别格式的数据等,同样要遵照类型规范。
例如,在一个返回文件下载的路由中,需要正确设置响应头来指示文件类型等信息:
  1. import express from 'express';
  2. import { Request, Response } from 'express';
  3. import path from 'path';
  4. import fs from 'fs';
  5. const router = express.Router();
  6. router.get('/download/:filename', (req: Request, res: Response) => {
  7.   const fileName = req.params.filename;
  8.   const filePath = path.join(__dirname, 'uploads', fileName);
  9.   const fileStream = fs.createReadStream(filePath);
  10.   res.setHeader('Content-Type', 'application/octet-stream');
  11.   res.setHeader('Content-Disposition', `attachment; filename="${fileName}"`);
  12.   fileStream.pipe(res);
  13. });
  14. export default router;
复制代码
在这个示例中,设置了响应头的 Content-Type 和 Content-Disposition 属性,用于告知客户端这是一个文件流下载,并且指定了文件名等信息,整个过程中 res 的各种方法调用(如 setHeader、pipe 等)都符合 Response 类型的界说和要求,确保了响应操作的正确性。
3、中间件类型处理

Express 框架中的中间件在 TypeScript 中也需要进行类型界说,以确保其在处理请求和通报控制流时的类型安全。
例如,创建一个简单的日志记载中间件,用于记载每个请求的相干信息:
  1. import { Request, Response, NextFunction } from 'express';
  2. const loggerMiddleware = (req: Request, res: Response, next: NextFunction) => {
  3.   console.log(`Received request: ${req.method} ${req.url}`);
  4.   next();
  5. };
  6. export default loggerMiddleware;
复制代码
在这个中间件函数中,参数按照 Request、Response 和 NextFunction(用于调用下一个中间件或路由处理函数的函数类型)的顺序界说,在中间件内部可以访问和处理请求相干的信息,然后通过调用 next() 函数将控制流通报给下一个中间件或路由处理函数,遵照了正确的类型规范。
三、数据库交互

(一)使用 Type - Safe 的数据库驱动(如 TypeORM)

TypeORM 是一个非常流行的支持 Type - Safe(类型安全)的 Node.js 数据库 ORM(对象关系映射)框架,它答应使用面向对象的方式与数据库进行交互,并且在整个过程中利用 TypeScript 的类型系统确保类型的正确性。
1、安装 TypeORM 及相干依赖

首先需要安装 TypeORM 以及对应数据库的驱动(以 MySQL 为例),同时还要安装 TypeORM 的类型界说包,下令如下:
  1. npm install typeorm mysql2 @types/mysql2
复制代码
2、配置数据库连接

在项目中创建一个 ormconfig.json 文件(也可以使用 JavaScript 或 TypeScript 文件来配置,这里以 .json 文件为例)用于配置数据库连接相干信息,示例如下:
  1. {
  2.   "type": "mysql",
  3.   "host": "localhost",
  4.   "port": 3306,
  5.   "username": "root",
  6.   "password": "your_password",
  7.   "database": "your_database_name",
  8.   "synchronize": true,
  9.   "logging": true,
  10.   "entities": ["src/entities/*.ts"],
  11.   "migrations": ["src/migrations/*.ts"],
  12.   "subscribers": ["src/subscribers/*.ts"]
  13. }
复制代码
解释关键配置项:


  • type:指定数据库类型,这里是 mysql。
    host、port、username、password、database:分别对应数据库的主机地址、端口号、用户名、密码和数据库名称,根据实际情况进行填写。
  • synchronize:设置为 true 时,TypeORM 会主动根据实体类(背面会介绍)的界说来创建、更新数据库表结构,但在生产情况中要谨慎使用,发起使用数据库迁移(migrations)来管理表结构变化。
  • logging:开启日志记载,方便检察数据库操作的相干情况,好比实行的 SQL 语句等。
  • entities:界说了实体类文件的路径,实体类用于映射数据库中的表结构,TypeORM 会根据这些实体类来进行数据库操作。
  • migrations 和 subscribers:分别用于配置数据库迁移文件和订阅者文件的路径,用于更复杂的数据库结构变动管理和事件监听等功能。
(二)界说数据库模型和操作的类型(增编削查)

1、界说数据库模型(实体类)

使用 TypeORM,需要创建实体类来形貌数据库中的表结构以及表与表之间的关系。例如,创建一个简单的 User 实体类,对应数据库中的 users 表:
  1. import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
  2. @Entity()
  3. class User {
  4.   @PrimaryGeneratedColumn()
  5.   id: number;
  6.   @Column()
  7.   username: string;
  8.   @Column()
  9.   password: string;
  10. }
  11. export default User;
复制代码
在上述代码中:


  • 使用 @Entity() 装饰器标记这个类是一个实体类,对应数据库中的一张表。
  • @PrimaryGeneratedColumn() 装饰器用于界说主键列,这里表现 id 列是自增的主键,类型为 number。
  • @Column() 装饰器用于界说普通列,如 username 和 password 列,分别对应数据库表中的相应字段,类型都为 string。
2、数据库操作的类型安全实现(增编削查)

基于上述界说的实体类,可以进行各种数据库操作,并且在操作过程中保持类型安全。
例如,进行简单的查询操作,获取所有用户信息:
  1. import { getConnection } from 'typeorm';
  2. import User from './entities/User';
  3. async function getUsers() {
  4.   const connection = await getConnection();
  5.   const users = await connection.getRepository(User).find();
  6.   return users;
  7. }
  8. // 使用示例
  9. (async () => {
  10.   const allUsers = await getUsers();
  11.   console.log(allUsers);
  12. })();
复制代码
在这个查询示例中,首先通过 getConnection() 方法获取数据库连接,然后使用 connection.getRepository(User) 获取 User 实体类对应的数据库操作仓库,最后调用 find() 方法来查询所有用户信息,返回的 users 效果类型是 User[],即一个 User 类型的数组,编译器能够清楚知道查询效果的结构,方便后续进行处理(好比遍历用户列表、访问用户的各个属性等操作)。
对于插入数据(新增用户)操作,示例如下:
  1. import { getConnection } from 'typeorm';
  2. import User from './entities/User';
  3. async function createUser(newUser: User) {
  4.   const connection = await getConnection();
  5.   const userRepository = connection.getRepository(User);
  6.   return await userRepository.save(newUser);
  7. }
  8. // 使用示例
  9. (async () => {
  10.   const newUser: User = {
  11.     username: 'new_user',
  12.     password: 'new_password'
  13.   };
  14.   const createdUser = await createUser(newUser);
  15.   console.log(createdUser);
  16. })();
复制代码
在插入操作中,界说了 createUser 函数吸收一个 User 类型的参数 newUser,然后将其生存到数据库中,返回的 createdUser 同样是 User 类型,确保了新增数据的类型一致性,整个数据库的增编削查操作在 TypeORM 的资助下都能很好地遵照 TypeScript 的类型规范,减少因类型不匹配等题目导致的错误,提高后端代码的质量和可维护性。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

光之使者

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表