生成/运行TypeORM迁移前如何预加载外部文件与模块?
TypeORM CLI 是独立于NestJS应用启动的Node进程,不会自动加载你在main.ts里引入的Array原型扩展实现,同时ts-node默认不会主动扫描你放在自定义目录下的.d.ts类型声明文件,两个问题叠加就会出现TS2339: Property 'undupe' does not exist的报错,和你之前Jest遇到的问题本质完全一致——都是独立运行环境没有预加载全局扩展和对应类型声明。
按配置成本从低到高可选以下方案:
方案1:修改CLI启动命令,直接预加载扩展(最快生效)
首先检查项目根目录的tsconfig.json,确保你的类型声明目录被include字段覆盖:
{ "compilerOptions": { // 保留原有其他配置 }, "include": ["src/**/*", "src/declarations/**/*.d.ts"] }
然后修改package.json里的typeorm启动脚本,给ts-node加--files参数强制加载include内的声明文件,同时通过--require参数提前加载你的Array扩展实现:
{ "scripts": { "typeorm": "ts-node --files --require ./src/implementations/array.implementation.ts ./node_modules/typeorm/cli.js" } }
后续生成迁移直接执行yarn typeorm migration:generate -n SomeMigration即可,不需要再用原来的node启动命令。
如果项目配置了tsconfig路径别名,额外加tsconfig-paths/register的预加载即可:
{ "scripts": { "typeorm": "ts-node --files -r tsconfig-paths/register -r ./src/implementations/array.implementation.ts ./node_modules/typeorm/cli.js" } }
方案2:在TypeORM数据源配置文件中加载扩展(更规范)
如果你用的是TypeORM 0.3.x版本推荐的独立数据源配置(data-source.ts),直接在文件最顶部引入扩展实现,让CLI加载数据源时自动完成预加载:
// src/data-source.ts import './implementations/array.implementation'; // 放在所有import最前面 import { DataSource } from 'typeorm'; export const AppDataSource = new DataSource({ // 保留原有数据库连接、实体、迁移路径等配置 });
对应的启动脚本调整为指定数据源路径即可:
{ "scripts": { "typeorm": "ts-node --files -r tsconfig-paths/register ./node_modules/typeorm/cli.js -d ./src/data-source.ts" } }
这种方式不需要在脚本里重复写扩展路径,后续加其他全局扩展也只需要在数据源文件顶部引入一次,维护成本更低。
方案3:配置TS自动识别全局声明
如果不想每次给命令加--files参数,可以在tsconfig.json的compilerOptions里配置typeRoots,让TS默认加载你自定义的声明目录:
{ "compilerOptions": { // 原有其他配置 "typeRoots": ["node_modules/@types", "src/declarations"] } }
配置后所有ts-node启动的脚本都会自动读取src/declarations下的所有.d.ts文件,不会再出现类型不存在的报错。
- 不要在单个业务文件里重复import扩展实现文件,原型扩展是挂载在全局构造函数上的,只需要在进程启动的入口加载一次即可,重复引入没有实际作用。
- 不要把扩展实现代码写在
.d.ts文件里,.d.ts仅做类型声明,实现逻辑必须放在.ts文件中在运行时加载。
内容的提问来源于stack exchange,提问作者WTomas

