MST

星途 面试题库

面试题:TypeScript接口interface在复杂项目架构中的设计与实践

在一个大型前端项目中,涉及用户管理模块、订单模块和商品模块。请使用接口interface设计一套类型系统,用于描述各模块之间的数据交互和方法调用。例如,用户模块可能有获取用户信息的方法,订单模块可能需要根据用户信息创建订单,商品模块可能需要向订单模块提供商品详情。要求清晰地展示接口的定义、如何在不同模块间共享和使用这些接口,以及如何通过接口来保证数据的一致性和可维护性,同时阐述在项目迭代过程中,如何基于这套接口类型系统进行扩展性设计。
19.1万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

1. 接口定义

用户模块接口

// 用户信息接口
interface UserInfo {
  id: number;
  name: string;
  email: string;
}

// 用户模块接口,定义获取用户信息方法
interface UserModule {
  getUserInfo(): UserInfo;
}

商品模块接口

// 商品详情接口
interface ProductDetail {
  id: number;
  name: string;
  price: number;
}

// 商品模块接口,定义提供商品详情方法
interface ProductModule {
  getProductDetail(productId: number): ProductDetail;
}

订单模块接口

// 订单信息接口
interface OrderInfo {
  id: number;
  userId: number;
  productIds: number[];
  totalPrice: number;
}

// 订单模块接口,定义创建订单方法
interface OrderModule {
  createOrder(userInfo: UserInfo, productDetails: ProductDetail[]): OrderInfo;
}

2. 接口共享与使用

假设使用 TypeScript 开发项目,这些接口可以定义在一个公共的 types 文件夹下的 common.ts 文件中,各个模块通过导入该文件来使用接口。 例如,在用户模块的实现文件 userModule.ts 中:

import { UserModule, UserInfo } from './common';

class UserModuleImpl implements UserModule {
  getUserInfo(): UserInfo {
    // 实际从后端获取或本地存储获取用户信息
    return {
      id: 1,
      name: 'John Doe',
      email: 'johndoe@example.com'
    };
  }
}

在商品模块的实现文件 productModule.ts 中:

import { ProductModule, ProductDetail } from './common';

class ProductModuleImpl implements ProductModule {
  getProductDetail(productId: number): ProductDetail {
    // 实际从后端获取商品详情
    return {
      id: productId,
      name: 'Sample Product',
      price: 100
    };
  }
}

在订单模块的实现文件 orderModule.ts 中:

import { OrderModule, OrderInfo, UserInfo, ProductDetail } from './common';

class OrderModuleImpl implements OrderModule {
  createOrder(userInfo: UserInfo, productDetails: ProductDetail[]): OrderInfo {
    const totalPrice = productDetails.reduce((acc, product) => acc + product.price, 0);
    return {
      id: new Date().getTime(),
      userId: userInfo.id,
      productIds: productDetails.map(product => product.id),
      totalPrice
    };
  }
}

3. 保证数据一致性和可维护性

通过接口定义明确了各模块之间的数据交互和方法调用规范。

  • 数据一致性:每个模块都按照接口规定的格式提供和接收数据,例如订单模块接收符合 UserInfoProductDetail 接口格式的数据,确保了数据结构的统一,避免因数据格式不一致导致的错误。
  • 可维护性:如果某个模块内部实现发生变化,只要接口不变,其他依赖该模块的部分无需修改。例如用户模块内部获取用户信息的方式从本地存储改为后端 API 获取,只要 getUserInfo 方法返回的数据符合 UserInfo 接口,订单模块和其他依赖用户信息的模块都不受影响。

4. 扩展性设计

在项目迭代过程中:

  • 新增功能:如果需要新增功能,比如增加用户的地址信息。可以在 UserInfo 接口中新增 address 字段,然后各依赖 UserInfo 接口的模块(如订单模块在创建订单时可能需要用户地址)按照新的接口定义调整代码。
  • 修改功能:如果修改商品模块提供商品详情的逻辑,只要 getProductDetail 方法的输入输出依然符合 ProductModule 接口定义,其他模块不受影响。若需要修改接口,例如增加商品的库存信息,应尽量采用兼容方式,如在 ProductDetail 接口中新增可选字段 stock?: number,这样老的依赖代码可能无需修改即可继续工作,而新功能可以利用新字段。
  • 删除功能:如果要删除某个接口方法或字段,应先标记为废弃,通知相关模块开发者逐步迁移,确保在所有模块都不再依赖后再彻底删除。这样基于接口类型系统,可以在项目迭代过程中有效控制变化带来的影响,实现良好的扩展性。