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

如何开发同时支持JavaScript与TypeScript的TypeScript类库?

编写同时支持JavaScript与TypeScript的TypeScript类库指南

核心原则

遵循「API一致性」:确保TypeScript和JavaScript用户调用库的方式完全一致,避免出现仅TS可用或仅JS可用的API,参考Vue的设计思路——让两种环境下的API体验无差异。

具体实践建议

  • 禁用TypeScript专属编译时特性
    不要依赖参数装饰器、类装饰器这类仅在TS编译阶段生效的特性,它们编译后不会保留有效JS逻辑,会导致JS用户无法正常使用API。
    反例(依赖装饰器的代码):

    class DataService {
      constructor(@Inject('API_CONFIG') private config: ApiConfig) {}
    }
    

    正例(JS友好的写法):

    class DataService {
      constructor(config: ApiConfig) {
        this.config = config;
      }
    }
    // 额外提供工厂函数简化调用
    export function createDataService(config: ApiConfig) {
      return new DataService(config);
    }
    
  • 基于标准JS语法设计API
    优先使用函数、普通对象、原生类(不含TS专属修饰符)来设计API,这些结构编译后与原生JS表现完全一致。比如Vue的defineComponent本质是接收普通对象的函数,TS用户能获得类型提示,JS用户直接传对象即可调用。
    示例:

    interface ComponentOptions {
      props?: Record<string, any>;
      setup?: () => void;
    }
    export function defineComponent(options: ComponentOptions) {
      // 内部处理逻辑
      return options;
    }
    
  • 类型定义与JS逻辑分离
    用interface、type编写完整的类型定义(开启tsconfig.json的declaration: true生成.d.ts文件),为TS用户提供IDE友好的类型提示,但不要让类型定义影响JS代码的运行。同时在JS层面做必要的参数校验,避免TS的编译时检查缺失导致JS用户出错。
    示例:

    interface InitConfig {
      timeout: number;
      baseUrl: string;
    }
    export function init(config: InitConfig) {
      // JS层面参数校验
      if (typeof config.timeout !== 'number' || config.timeout <= 0) {
        throw new Error('timeout必须是大于0的数字');
      }
      // 核心逻辑
    }
    
  • 配置TS编译确保JS产物兼容性
    在tsconfig.json中合理设置:

    • target:选择兼容范围广的ES版本(如ES2018),避免编译出过于前沿的语法;
    • module:根据库的使用场景选择ESNext或CommonJS;
    • declaration: true:生成类型定义文件;
    • isolatedModules: true:确保每个文件可独立编译,避免编译后出现异常代码。
  • 同时覆盖JS和TS测试场景
    编写测试用例时,既要用TS验证类型提示和类型检查是否正常,也要用JS编写测试,确保API在纯JS环境下能正常调用、参数传递和返回值符合预期。

需要避免的坑

  • 不要用enum作为对外API的一部分:TS的enum编译后生成的对象在不同编译配置下可能存在差异,建议用as const标记的对象字面量替代:
    // 推荐写法
    export const Status = {
      Active: 0,
      Inactive: 1
    } as const;
    
  • 避免使用namespace:改用ES模块的import/export,namespace编译后的JS代码结构不直观,会增加JS用户的导入成本。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 13:52:45