You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript 4.0+ 能否通过泛型定义可动态扩展服务属性的类型?

实现方案

完全可以通过TypeScript泛型特性实现需求,核心思路是利用泛型参数推导+交叉类型动态生成Device实例的类型,在编译期严格控制可访问的服务属性。

前置约定

首先定义各服务类,以及服务到挂载属性的映射规则:

// 示例服务类
class ControlService {
  open() { console.log('打开设备') }
}
class MonitorService {
  getStatus() { return '运行正常' }
}

// 约定:服务类 -> 挂载属性名的映射
type ServicePropMap = {
  ControlService: 'control'
  MonitorService: 'monitor'
}
type AllSupportedService = ControlService | MonitorService

类型工具定义

编写工具类型将传入的服务实例元组转换为Device实例上的属性类型:

// 单个服务实例转对应属性对象
type ServiceToProp<T extends AllSupportedService> = T extends { constructor: { name: keyof ServicePropMap } }
  ? Record<ServicePropMap[T['constructor']['name']], T>
  : never

// 服务实例元组转交叉类型的属性集合
type DeviceServiceProps<T extends AllSupportedService[]> = 
  T[number] extends infer S ? (S extends AllSupportedService ? ServiceToProp<S> : never) : never

Device类实现

通过构造函数类型断言,让实例类型自动合并基础方法和挂载的服务属性:

class _Device<T extends AllSupportedService[] = []> {
  constructor(...services: T) {
    // 运行时挂载服务到对应属性
    services.forEach(service => {
      const prop = ServicePropMap[service.constructor.name as keyof ServicePropMap]
      // @ts-ignore 运行时逻辑安全,无需类型检查
      this[prop] = service
    })
  }

  // Device本身的基础方法
  reboot() { console.log('设备重启中') }
}

// 对外导出的Device类型,自动合并服务属性
export const Device = _Device as unknown as 
  new <T extends AllSupportedService[] = []>(...services: T) => _Device<T> & DeviceServiceProps<T>

效果验证

// 传入ControlService的场景
const device = new Device(new ControlService())
device.control.open() // ✅ 类型正常,编译通过
device.reboot() // ✅ 基础方法正常访问
device.monitor.getStatus() // ❌ 编译报错:属性monitor不存在

// 不传任何服务的场景
const emptyDevice = new Device()
emptyDevice.control.open() // ❌ 编译报错:属性control不存在
emptyDevice.reboot() // ✅ 基础方法正常访问

扩展说明

如果不希望依赖类名做映射,也可以给每个服务类添加静态属性mountProp来声明挂载的属性名,调整映射规则即可,使用逻辑完全一致。


内容的提问来源于stack exchange,提问作者Luftzig

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 08:24:03