TypeScript 与后端开发Node.js

文章目录
  • 一、搭建 TypeScript + Node.js 项目
    • (一)初始化项目并安装相关依赖
      • 1、创建项目目录并初始化
      • 2、安装必要的依赖包
    • (二)配置 TypeScript 编译选项(如模块解析方式适合后端)
  • 二、编写服务器代码
    • (一)定义路由类型(使用 Express 等框架)
    • (二)处理请求和响应的类型(包括中间件的类型)
      • 1、请求类型处理
      • 2、响应类型处理
      • 3、中间件类型处理
  • 三、数据库交互
    • (一)使用 Type - Safe 的数据库驱动(如 TypeORM)
      • 1、安装 TypeORM 及相关依赖
      • 2、配置数据库连接
    • (二)定义数据库模型和操作的类型(增删改查)
      • 1、定义数据库模型(实体类)
      • 2、数据库操作的类型安全实现(增删改查)

在这里插入图片描述

一、搭建 TypeScript + Node.js 项目

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

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

首先,创建一个新的项目文件夹,例如通过命令行操作:

mkdir my-node-ts-project
cd my-node-ts-project
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:

npm install express
npm install @types/express --save-dev

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

在项目根目录下创建 tsconfig.json 文件,用于配置 TypeScript 的编译选项。以下是一个适合后端开发的基本配置示例:

{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "outDir": "dist",
    "rootDir": "src",
    "strict": true,
    "esModuleInterop": true,
    "sourceMap": true,
    "resolveJsonModule": true
  },
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules"]
}

解释一下关键配置项:

  • 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 文件用于定义用户相关的路由:

import express from 'express';
import { Request, Response } from 'express';

const router = express.Router();

// 定义一个获取用户信息的路由
router.get('/users/:id', (req: Request, res: Response) => {
  const userId = req.params.id;
  // 这里可以假设从数据库等地方获取用户信息并返回,暂时模拟返回一个固定信息
  const user = { id: userId, name: 'John Doe' };
  res.json(user);
});

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 数据(假设用户注册信息包含用户名和密码):

import express from 'express';
import { Request, Response } from 'express';

interface UserRegistration {
  username: string;
  password: string;
}

const router = express.Router();

router.post('/register', (req: Request<{}, {}, UserRegistration>, res: Response) => {
  const userData: UserRegistration = req.body;
  console.log(`Received registration data: ${JSON.stringify(userData)}`);
  // 这里可以进行后续的业务逻辑,比如将用户信息存入数据库等操作
  res.status(201).send('Registration successful');
});

export default router;

在这个示例中,定义了 UserRegistration 接口来描述用户注册信息的结构(包含用户名和密码两个属性,类型都为 string),在路由处理函数的 Request 类型参数中,通过泛型指定了请求体的类型为 UserRegistration,这样在函数内部就能安全地从 req.body 获取并使用用户注册信息了,编译器会确保类型的一致性。

2、响应类型处理

对于响应对象(Response),可以根据不同的业务需求设置响应状态码、响应头以及返回不同格式的数据等,同样要遵循类型规范。
例如,在一个返回文件下载的路由中,需要正确设置响应头来指示文件类型等信息:

import express from 'express';
import { Request, Response } from 'express';
import path from 'path';
import fs from 'fs';

const router = express.Router();

router.get('/download/:filename', (req: Request, res: Response) => {
  const fileName = req.params.filename;
  const filePath = path.join(__dirname, 'uploads', fileName);
  const fileStream = fs.createReadStream(filePath);
  res.setHeader('Content-Type', 'application/octet-stream');
  res.setHeader('Content-Disposition', `attachment; filename="${fileName}"`);
  fileStream.pipe(res);
});

export default router;

在这个示例中,设置了响应头的 Content-Type 和 Content-Disposition 属性,用于告知客户端这是一个文件流下载,并且指定了文件名等信息,整个过程中 res 的各种方法调用(如 setHeader、pipe 等)都符合 Response 类型的定义和要求,确保了响应操作的正确性。

3、中间件类型处理

Express 框架中的中间件在 TypeScript 中也需要进行类型定义,以确保其在处理请求和传递控制流时的类型安全。
例如,创建一个简单的日志记录中间件,用于记录每个请求的相关信息:

import { Request, Response, NextFunction } from 'express';

const loggerMiddleware = (req: Request, res: Response, next: NextFunction) => {
  console.log(`Received request: ${req.method} ${req.url}`);
  next();
};

export default loggerMiddleware;

在这个中间件函数中,参数按照 Request、Response 和 NextFunction(用于调用下一个中间件或路由处理函数的函数类型)的顺序定义,在中间件内部可以访问和处理请求相关的信息,然后通过调用 next() 函数将控制流传递给下一个中间件或路由处理函数,遵循了正确的类型规范。

三、数据库交互

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

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

1、安装 TypeORM 及相关依赖

首先需要安装 TypeORM 以及对应数据库的驱动(以 MySQL 为例),同时还要安装 TypeORM 的类型定义包,命令如下:

npm install typeorm mysql2 @types/mysql2
2、配置数据库连接

在项目中创建一个 ormconfig.json 文件(也可以使用 JavaScript 或 TypeScript 文件来配置,这里以 .json 文件为例)用于配置数据库连接相关信息,示例如下:

{
  "type": "mysql",
  "host": "localhost",
  "port": 3306,
  "username": "root",
  "password": "your_password",
  "database": "your_database_name",
  "synchronize": true,
  "logging": true,
  "entities": ["src/entities/*.ts"],
  "migrations": ["src/migrations/*.ts"],
  "subscribers": ["src/subscribers/*.ts"]
}

解释关键配置项:

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

(二)定义数据库模型和操作的类型(增删改查)

1、定义数据库模型(实体类)

使用 TypeORM,需要创建实体类来描述数据库中的表结构以及表与表之间的关系。例如,创建一个简单的 User 实体类,对应数据库中的 users 表:

import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';

@Entity()
class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  username: string;

  @Column()
  password: string;
}

export default User;

在上述代码中:

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

基于上述定义的实体类,可以进行各种数据库操作,并且在操作过程中保持类型安全。
例如,进行简单的查询操作,获取所有用户信息:

import { getConnection } from 'typeorm';
import User from './entities/User';

async function getUsers() {
  const connection = await getConnection();
  const users = await connection.getRepository(User).find();
  return users;
}

// 使用示例
(async () => {
  const allUsers = await getUsers();
  console.log(allUsers);
})();

在这个查询示例中,首先通过 getConnection() 方法获取数据库连接,然后使用 connection.getRepository(User) 获取 User 实体类对应的数据库操作仓库,最后调用 find() 方法来查询所有用户信息,返回的 users 结果类型是 User[],即一个 User 类型的数组,编译器能够清楚知道查询结果的结构,方便后续进行处理(比如遍历用户列表、访问用户的各个属性等操作)。
对于插入数据(新增用户)操作,示例如下:

import { getConnection } from 'typeorm';
import User from './entities/User';

async function createUser(newUser: User) {
  const connection = await getConnection();
  const userRepository = connection.getRepository(User);
  return await userRepository.save(newUser);
}

// 使用示例
(async () => {
  const newUser: User = {
    username: 'new_user',
    password: 'new_password'
  };
  const createdUser = await createUser(newUser);
  console.log(createdUser);
})();

在插入操作中,定义了 createUser 函数接收一个 User 类型的参数 newUser,然后将其保存到数据库中,返回的 createdUser 同样是 User 类型,确保了新增数据的类型一致性,整个数据库的增删改查操作在 TypeORM 的帮助下都能很好地遵循 TypeScript 的类型规范,减少因类型不匹配等问题导致的错误,提高后端代码的质量和可维护性。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/970714.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CAS单点登录(第7版)1.首页

如有疑问&#xff0c;请看视频&#xff1a;CAS单点登录&#xff08;第7版&#xff09; 面向所有地球人及其他地区的企业身份 Enterprise Identity for All Earthlings and Beyond 身份、单点登录和访问管理 Identity, Single Sign-On and Access Management 首页 Apereo CAS…

Unity学习part1

课程为b站【Unity教程】零基础带你从小白到超神 1、脚本执行顺序 unity的脚本执行顺序不像blender的修改器那样按顺序执行&#xff0c;而是系统默认给配置一个值&#xff0c;值越小&#xff0c;执行顺序越靠前&#xff08;注意&#xff0c;这个顺序是全局生效的&#xff09; …

Next.js【详解】CSS 样式方案

全局样式 Global CSS 默认已创建&#xff0c;即 src\app\globals.css&#xff0c;可根据需要修改 默认在全局布局中导入 src\app\layout.tsx import "./globals.css";组件样式 CSS Modules 新建文件 src\app\test\styles.module.css .red {color: red;}导入目标页面…

基于SpringBoot+Vue的求职招聘管理系统

系统展示 用户前台界面 管理员后台界面 系统背景 在数字化和信息化的时代背景下&#xff0c;求职招聘管理系统作为一种高效的线上服务平台&#xff0c;正逐渐改变着传统的招聘方式。随着互联网的普及和技术的不断进步&#xff0c;求职者与企业之间的信息交互变得越来越频繁和复…

#渗透测试#批量漏洞挖掘#致远互联AnalyticsCloud 分析云 任意文件读取

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…

CAS单点登录(第7版)3.安装

如有疑问&#xff0c;请看视频&#xff1a;CAS单点登录&#xff08;第7版&#xff09; 安装 要求 安装要求 根据配置组件的选择&#xff0c;可能还有其他要求&#xff0c;例如 LDAP 目录、数据库和缓存基础结构。但是&#xff0c;在大多数情况下&#xff0c;对于选择具有明确…

安装 Docker Desktop 修改默认安装目录到指定目录

Docker Desktop安装目录设置 Docker Desktop 默认安装位置 &#xff08;C:\Program Files\Docker\Docker) 是这个 &#xff0c;导致系统盘占用过大&#xff0c;大概2G ; 那么如何安装到其他磁盘呢&#xff1f; 根据docker desktop 官网 Docker Desktop install 我们可以看到&a…

网络安全威胁是什么

1.网络安全威胁的概念 网络安全威胁指网络中对存在缺陷的潜在利用&#xff0c;这些缺陷可能导致信息泄露、系统资源耗尽、非法访问、资源被盗、系统或数据被破坏等。 2.网络安全威胁的类型 物理威胁系统漏洞威胁身份鉴别威胁线缆连接威胁有害程序危险 &#xff08;1&#x…

Flutter_学习记录_动画的简单了解

用AnimationController简单实现如下的效果图&#xff1a; 1. 只用AnimationController实现简单动画 1.1 完整代码案例 import package:flutter/material.dart;class AnimationDemo extends StatefulWidget {const AnimationDemo({super.key});overrideState<AnimationDe…

数据结构与算法之排序算法-选择排序

排序算法是数据结构与算法中最基本的算法之一&#xff0c;其作用就是将一些可以比较大小的数据进行有规律的排序&#xff0c;而想要实现这种排序就拥有很多种方法~ 那么我将通过几篇文章&#xff0c;将排序算法中各种算法细化的&#xff0c;详尽的为大家呈现出来&#xff1a; &…

IOTDB安装部署

IOTDB一般用于工业互联网&#xff0c;至于具体的介绍请自行搜索 1.环境准备 安装前需要保证设备上配有 JDK>1.8 的运行环境&#xff0c;并配置好 JAVA_HOME 环境变量。 设置最大文件打开数为 65535。 关闭防火墙 systemctl stop firewalld.service systemctl disable …

游戏引擎学习第100天

仓库:https://gitee.com/mrxiao_com/2d_game_2 昨天的回顾 今天的工作重点是继续进行反射计算的实现。昨天&#xff0c;我们开始了反射和环境贴图的工作&#xff0c;成功地根据法线显示了反射效果。然而&#xff0c;我们还没有实现反射向量的计算&#xff0c;导致反射交点的代…

分布式 NewSQL 数据库(TiDB)

TiDB 是一个分布式 NewSQL 数据库。它支持水平弹性扩展、ACID 事务、标准 SQL、MySQL 语法和 MySQL 协议&#xff0c;具有数据强一致的高可用特性&#xff0c;是一个不仅适合 OLTP 场景还适合 OLAP 场景的混合数据库。 TiDB是 PingCAP公司自主设计、研发的开源分布式关系型数据…

Vue响应式原理实现总结(数据劫持Object.defineProperty/Proxy+发布订阅者设计模式)

Vue的响应式主要分为数据劫持和发布订阅模式。Vue2用的是Object.defineProperty,而Vue3改用Proxy。数据劫持就是在访问或修改对象属性时进行拦截,然后触发相应的更新。发布订阅模式则是用来收集依赖(比如视图更新函数),当数据变化时通知这些依赖执行。 总结一下,关键点包…

以若依移动端版为基础,实现uniapp的flowable流程管理

1.前言 此代码是若依移动端版为基础&#xff0c;实现flowable流程管理&#xff0c;支持H5、APP和微信小程序三端。其中&#xff0c;APP是在安卓在雷电模拟器环境下完成的&#xff0c;其他环境未测试&#xff0c;此文章中所提及的APP均指上述环境。移动端是需要配合若依前后端分…

封装一个sqlite3动态库

作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、项目案例 二…

Qt Creator 5.0.2 (Community)用久了突然变得很卡

目录 1.现象 2.解决方案 1.现象 很久没有用Qt Creator开发项目了&#xff0c;刚刚结束的项目又是用VS2019开发的&#xff1b;这两天刚好有时间去学习一下Qt&#xff0c;刚好要用Qt Creator&#xff0c;结果一打开就没反应&#xff0c;主界面显示出来要好几分钟&#xff0c;最…

[C++]多态详解

目录 一、多态的概念 二、静态的多态 三、动态的多态 3.1多态的定义 3.2虚函数 四、虚函数的重写&#xff08;覆盖&#xff09; 4.1虚函数 4.2三同 4.3两种特殊情况 &#xff08;1&#xff09;协变 &#xff08;2&#xff09;析构函数的重写 五、C11中的final和over…

mac 意外退出移动硬盘后再次插入移动硬盘不显示怎么办

第一步&#xff1a;sudo ps aux | grep fsck 打开mac控制台输入如下指令&#xff0c;我们看到会出现两个进程&#xff0c;看进程是root的这个 sudo ps aux|grep fsck 第二步&#xff1a;杀死进程 在第一步基础上我们知道不显示u盘的进程是&#xff1a;62319&#xff0c;我们…

国家队出手!DeepSeek上线国家超算互联网平台!

目前,国家超算互联网平台已推出 DeepSeek – R1 模型的 1.5B、7B、8B、14B 版本,后续还会在近期更新 32B、70B 等版本。 DeepSeek太火爆了!在这个春节档,直接成了全民热议的话题。 DeepSeek也毫无悬念地干到了全球增速最快的AI应用。这几天,国内的云计算厂家都在支持Dee…