MST

星途 面试题库

面试题:TypeScript 在 Node.js 企业级后端应用中的类型安全实践

在 Node.js 企业级后端应用开发中,如何利用 TypeScript 的类型系统确保代码的类型安全?比如在处理数据库查询结果、API 接口参数校验等场景下,描述具体的实现思路和可能用到的技术手段。
13.9万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

处理数据库查询结果

  1. 定义接口或类型别名:根据数据库表结构,定义对应的 TypeScript 接口或类型别名。例如,若有一个用户表,包含 idnameemail 字段,可以定义如下接口:
interface User {
  id: number;
  name: string;
  email: string;
}
  1. 使用类型断言:在获取数据库查询结果时,使用类型断言将结果转换为定义好的类型。假设使用 mysql2 库进行数据库查询:
import mysql from'mysql2';

const connection = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: 'password',
  database: 'test'
});

connection.query('SELECT * FROM users WHERE id =?', [1], (error, results) => {
  if (error) throw error;
  const user = results[0] as User;
  console.log(user.name);
});
  1. 使用泛型:一些数据库操作库支持泛型,可以直接指定返回结果的类型。例如,使用 knex.js
import knex from 'knex';

const db = knex({
  client:'mysql2',
  connection: {
    host: 'localhost',
    user: 'root',
    password: 'password',
    database: 'test'
  }
});

db.select<User>('*').from('users').where('id', 1).then((users) => {
  const user = users[0];
  console.log(user.name);
});

API 接口参数校验

  1. 定义参数接口:为 API 接口的输入参数定义接口。例如,对于一个注册用户的接口,参数可能包含 nameemailpassword
interface RegisterUserParams {
  name: string;
  email: string;
  password: string;
}
  1. 结合验证库:可以使用 joi 等验证库来进行实际的参数验证,并结合 TypeScript 类型系统。首先安装 joinpm install joi
import Joi from 'joi';

const registerUserSchema = Joi.object({
  name: Joi.string().required(),
  email: Joi.string().email().required(),
  password: Joi.string().min(6).required()
});

export const validateRegisterUser = (params: RegisterUserParams) => {
  const { error } = registerUserSchema.validate(params);
  if (error) {
    throw new Error(error.details[0].message);
  }
  return true;
};
  1. 在路由中使用:在 Express 等框架的路由处理函数中使用验证函数:
import express from 'express';
const app = express();
app.use(express.json());

app.post('/register', (req, res) => {
  try {
    validateRegisterUser(req.body);
    // 处理注册逻辑
    res.send('User registered successfully');
  } catch (error) {
    res.status(400).send((error as Error).message);
  }
});

const port = 3000;
app.listen(port, () => {
  console.log(`Server running on port ${port}`);
});
  1. 使用装饰器(可选):对于基于类的路由框架(如 routing-controllers),可以使用装饰器来进行参数验证和类型检查。首先安装 routing-controllersclass-validatornpm install routing-controllers class-validator
import { Controller, Post, Body, UseBefore } from 'routing-controllers';
import { IsEmail, MinLength, validate } from 'class-validator';

class RegisterUserDto {
  @MinLength(1)
  name: string;

  @IsEmail()
  email: string;

  @MinLength(6)
  password: string;
}

@Controller()
export class UserController {
  @Post('/register')
  async registerUser(@Body() user: RegisterUserDto) {
    const errors = await validate(user);
    if (errors.length > 0) {
      throw new Error('Validation failed');
    }
    // 处理注册逻辑
    return 'User registered successfully';
  }
}