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

如何用TypeScript编写兼容Node.js与浏览器的可复用类?

嗨!既然你已经熟悉 TypeScript 和 JavaScript,但刚接触 Node.js,那咱们一步步来搞定如何编写能同时在 Node.js 和浏览器环境复用的代码,尤其是你提到的那个类。下面是一套清晰的方案:


1. 编写与环境无关的 TypeScript 类

首先,核心类要避免直接依赖 Node.js 专属 API(比如 fs、process)或浏览器专属 API(比如 window、document)。如果确实需要环境相关功能,通过条件判断兼容即可。

示例代码 src/MyAbstractClass.ts:

export abstract class MyAbstractClass {
  protected name: string;

  constructor(name: string) {
    this.name = name;
  }

  abstract doSomething(): void;

  // 通用方法,不依赖任何环境
  greet(): string {
    return `Hello, ${this.name}!`;
  }

  // 兼容环境的逻辑示例
  getEnvironment(): string {
    if (typeof window !== 'undefined') {
      return 'browser';
    } else if (typeof process !== 'undefined' && process.versions.node) {
      return 'node';
    }
    return 'unknown';
  }
}

2. 配置 TypeScript 生成双环境代码

我们需要让 TypeScript 分别生成适合 Node.js 的 CommonJS 模块和适合浏览器的 ES 模块。创建两个配置文件:

针对 Node.js 的 tsconfig.node.json

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "CommonJS",
    "outDir": "./dist/node",
    "declaration": true,
    "strict": true,
    "esModuleInterop": true
  },
  "include": ["src/**/*"]
}

针对浏览器的 tsconfig.browser.json

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "outDir": "./dist/browser",
    "declaration": true,
    "strict": true,
    "lib": ["ES2020", "DOM"] // 引入浏览器相关标准库
  },
  "include": ["src/**/*"]
}

在 package.json 中添加构建脚本:

{
  "scripts": {
    "build": "tsc -p tsconfig.node.json && tsc -p tsconfig.browser.json"
  }
}

运行 npm run build 后,dist/node 和 dist/browser 目录会生成对应环境的 JS 文件和类型定义。

3. 让 Node.js 自动识别模块(可选)

在 package.json 中添加条件导出,Node.js 会自动匹配对应环境的模块:

{
  "exports": {
    ".": {
      "node": "./dist/node/MyAbstractClass.js",
      "default": "./dist/browser/MyAbstractClass.js"
    }
  },
  "types": "./dist/node/MyAbstractClass.d.ts"
}

4. 在浏览器中使用

方式一:ES 模块引入(现代浏览器推荐)

<!DOCTYPE html>
<html>
<head>
  <title></title>
  <meta charset="utf-8" />
</head>
<body>
  <script type="module">
    import { MyAbstractClass } from './dist/browser/MyAbstractClass.js';
    
    // 实现抽象类
    class MyConcreteClass extends MyAbstractClass {
      doSomething() {
        console.log(`Browser is doing something for ${this.name}`);
      }
    }

    const instance = new MyConcreteClass('Silas');
    console.log(instance.greet()); // 输出 Hello, Silas!
    console.log(instance.getEnvironment()); // 输出 browser
  </script>
</body>
</html>

方式二:全局变量引入(兼容旧浏览器)

用 esbuild 打包成 IIFE 格式(类会挂载到全局):

npx esbuild ./src/MyAbstractClass.ts --bundle --outfile=./js/myabstractclass.js --format=iife --global-name=MyLib

然后在 HTML 中引入:

<script type="text/javascript" src="/js/myabstractclass.js"></script>
<script>
  class MyConcreteClass extends MyLib.MyAbstractClass {
    doSomething() {
      console.log(`Doing something in browser!`);
    }
  }
  const instance = new MyConcreteClass('Test');
  console.log(instance.greet());
</script>

5. 在 Node.js 中测试

创建 test-node.js:

const { MyAbstractClass } = require('./dist/node/MyAbstractClass.js');

class MyConcreteClass extends MyAbstractClass {
  doSomething() {
    console.log(`Node.js is doing something for ${this.name}`);
  }
}

const instance = new MyConcreteClass('Silas');
console.log(instance.greet()); // 输出 Hello, Silas!
console.log(instance.getEnvironment()); // 输出 node
instance.doSomething();

运行 node test-node.js 即可看到结果。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:57:36