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

TypeScript如何加载JS文件中的schema变量并合并多文件内容?

实现TypeScript中加载多个JS Schema文件并合并的方案

我来一步步拆解这个需求,给你具体的实现方案:

1. 先调整JS Schema文件的导出方式

你的原始JS文件只是直接定义了var schema,但Node.js里要安全加载这个变量,最规范的做法是让文件导出它。修改后的JS文件长这样:

// schema1.js
module.exports = { 
  "date": Date.now(), 
  "someOtherField": 5 + 6, 
  "aMoreComplexField": { "foo": "bar" } 
};

要是你实在没法修改原JS文件,后面我也会给你一个应急方案,但优先选上面这种导出方式,更安全也更易维护。

2. TypeScript中的核心实现

根据你的需求,我分两种合并场景给出代码:浅合并(适合无嵌套或允许嵌套字段被覆盖)和深合并(保留嵌套对象的属性)。

基础版:浅合并

浅合并用Object.assign即可,后续加载的文件会覆盖前面的同名字段。我们先给Schema定义类型,让TS提供类型提示和检查:

import * as path from 'path';

// 定义Schema的类型,按需扩展字段
type Schema = {
  date: number;
  someOtherField?: number;
  aMoreComplexField?: {
    foo?: string;
  };
  // 允许其他任意字段
  [key: string]: any;
};

function loadSchema(...schemaFiles: string[]): Schema {
  let mergedSchema: Schema = {};

  for (const file of schemaFiles) {
    // 转成绝对路径,避免相对路径的坑
    const filePath = path.resolve(file);
    // 加载JS文件,用类型断言让TS识别结构
    const fileSchema = require(filePath) as Schema;
    // 合并到结果对象
    mergedSchema = Object.assign(mergedSchema, fileSchema);
  }

  // 这里添加你需要的额外操作,比如新增一个加载时间字段
  mergedSchema.loadTime = Date.now();

  return mergedSchema;
}

// 调用示例
const combinedSchema = loadSchema('./schema1.js', './schema2.js');
console.log(combinedSchema);

进阶版:深层合并

如果Schema包含嵌套对象,浅合并会直接覆盖整个嵌套对象,这时候需要用深合并。你可以自己实现一个简单的深合并函数,或者用lodash的merge(需先安装lodash包)。

先看自定义的深合并实现:

// 简单的深合并函数,支持对象嵌套,数组直接覆盖(可按需调整)
function deepMerge(target: any, source: any): any {
  const merged = { ...target };
  for (const key in source) {
    if (source.hasOwnProperty(key)) {
      // 如果是对象且不是数组,递归合并
      if (typeof source[key] === 'object' && source[key] !== null && !Array.isArray(source[key])) {
        merged[key] = deepMerge(target[key] || {}, source[key]);
      } else {
        // 基本类型和数组直接覆盖
        merged[key] = source[key];
      }
    }
  }
  return merged;
}

// 修改loadSchema里的合并逻辑
function loadSchema(...schemaFiles: string[]): Schema {
  let mergedSchema: Schema = {};

  for (const file of schemaFiles) {
    const filePath = path.resolve(file);
    const fileSchema = require(filePath) as Schema;
    // 用深合并替代Object.assign
    mergedSchema = deepMerge(mergedSchema, fileSchema);
  }

  // 额外操作示例
  mergedSchema.loadTime = Date.now();

  return mergedSchema;
}

3. 一些关键注意事项

  • 类型安全:定义Schema类型能帮你在开发时避免类型错误,TS会实时给出提示,大幅提升代码可靠性。
  • 文件路径:务必用path.resolve把相对路径转成绝对路径,不然在不同目录下运行代码可能出现文件找不到的问题。
  • 应急方案(不推荐):如果完全无法修改原JS文件,只能加载未导出的var schema,可以用fs读取文件内容再eval——但强烈不推荐,因为eval会执行任意代码,存在安全风险。示例代码:
    import * as fs from 'fs';
    import * as path from 'path';
    
    function loadUnmodifiedSchema(file: string): Schema {
      const filePath = path.resolve(file);
      const fileContent = fs.readFileSync(filePath, 'utf8');
      const context = {};
      // 执行文件代码,把schema变量存入context
      eval(`var schema; ${fileContent}; context.schema = schema;`);
      return context.schema as Schema;
    }
    
  • ES模块适配:如果你的TS项目用ES模块(tsconfig.json中"module": "ESNext"),可以用动态导入import()加载文件,此时函数要改成异步:
    async function loadSchema(...schemaFiles: string[]): Promise<Schema> {
      let mergedSchema: Schema = {};
      for (const file of schemaFiles) {
        const filePath = path.resolve(file);
        // 动态导入JS文件
        const { default: fileSchema } = await import(filePath);
        mergedSchema = deepMerge(mergedSchema, fileSchema);
      }
      mergedSchema.loadTime = Date.now();
      return mergedSchema;
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:54:47