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

如何用TypeScript从指定目录动态加载类并生成可实例化的Map集合

实现方案

动态批量导入目录文件并生成类映射的实现逻辑和你的运行/构建环境强相关,以下是不同场景的可用方案:

前置约定

默认你Shapes目录下的每个文件导出规则统一:要么默认导出对应类,要么导出与文件名同名的命名类,示例:

// Shapes/Square.ts 示例
export default class Square {
  // 类业务逻辑
}

同时提前定义Shape基类类型约束:

interface Shape {
  // 所有形状类的公共属性/方法定义
}

1. Node.js 原生环境(TS编译后运行在Node服务端)

直接用Node内置的fs、path模块读取目录+动态require实现:

import * as fs from 'fs'
import * as path from 'path'

export class Application {
  static getShapes(): Map<string, new () => Shape> {
    const shapeMap = new Map<string, new () => Shape>()
    // 按你实际项目路径调整Shapes目录的绝对路径
    const shapesDir = path.resolve(__dirname, './Shapes')
    // 读取目录下所有文件
    const files = fs.readdirSync(shapesDir)
    
    for (const file of files) {
      // 过滤非代码文件
      if (!file.endsWith('.ts') && !file.endsWith('.js')) continue
      // 提取不带后缀的文件名作为Map的key
      const fileName = path.basename(file, path.extname(file))
      // 动态导入模块
      const module = require(path.join(shapesDir, file))
      // 取导出的类,默认导出取module.default,命名导出取module[fileName]
      const ShapeClass = module.default || module[fileName]
      // 校验是可构造的类再存入Map
      if (typeof ShapeClass === 'function' && ShapeClass.prototype.constructor) {
        shapeMap.set(fileName, ShapeClass)
      }
    }
    return shapeMap
  }
}

使用方式和你的预期完全一致:

const instances = Application.getShapes()
const square = new (instances.get("Square")!)()

2. Vite 前端环境

用Vite内置的import.meta.globAPI实现批量导入,不需要操作文件系统:

export class Application {
  static async getShapes(): Promise<Map<string, new () => Shape>> {
    const shapeMap = new Map<string, new () => Shape>()
    // 批量匹配Shapes目录下所有ts文件,eager设为true表示直接同步导入所有模块
    const modules = import.meta.glob('./Shapes/*.ts', { eager: true })
    
    for (const [filePath, module] of Object.entries(modules)) {
      const fileName = filePath.split('/').pop()?.replace(/\.(ts|js)$/, '') as string
      const ShapeClass = (module as any).default || (module as any)[fileName]
      if (typeof ShapeClass === 'function' && ShapeClass.prototype.constructor) {
        shapeMap.set(fileName, ShapeClass)
      }
    }
    return shapeMap
  }
}

使用时因为是异步API,需要加await:

const instances = await Application.getShapes()
const square = new (instances.get("Square")!)()

3. Webpack 前端环境

用Webpack内置的require.contextAPI实现批量导入:

export class Application {
  static getShapes(): Map<string, new () => Shape> {
    const shapeMap = new Map<string, new () => Shape>()
    // 三个参数分别是:目标目录、是否遍历子目录、匹配文件的正则
    const context = require.context('./Shapes', false, /\.ts$/)
    
    context.keys().forEach((filePath: string) => {
      const fileName = filePath.replace(/^\.\/(.*)\.\w+$/, '$1')
      const module = context(filePath)
      const ShapeClass = module.default || module[fileName]
      if (typeof ShapeClass === 'function' && ShapeClass.prototype.constructor) {
        shapeMap.set(fileName, ShapeClass)
      }
    })
    return shapeMap
  }
}

注意事项

  • 如果你的类构造函数需要传参,把Map的泛型改成new (...args: any[]) => Shape即可
  • 新增形状类只需要放在Shapes目录下,不需要手动修改导入逻辑,会自动被识别加入映射
  • 生产构建时批量导入的文件默认会全部打包,不会被tree shaking误删,不需要额外配置

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 20:15:02