如何为可调用命名空间模式的通用JS库编写TypeScript类型声明?
解决方案
核心原理是TypeScript支持函数声明与同名命名空间声明合并,可以直接实现「可调用+附带属性方法」的类型定义,再配合顶层导出即可满足所有用法需求。
// 1. 声明可调用的主函数(可根据实际业务替换参数和返回值类型) declare function lib(input: string): number; // 2. 同名命名空间与函数合并,定义所有挂载在lib下的成员 declare namespace lib { // 所有对外暴露的方法、变量都在此处声明,仅需写一次 export function b(num: number): string; export const version: string; export function util(): void; } // 3. 导出命名导出的lib对象 export { lib }; // 4. 导出默认导出(可直接调用的lib) export default lib; // 5. 导出顶层独立成员,与lib下的成员一一对应 export const { b, version, util } = lib;
验证匹配的用法
你给出的两种ESM用法均可正常识别类型:
// 用法1:默认导入 import lib from "lib"; const x = lib("test"); const y = lib.b(123); // 用法2:命名导入顶层成员和lib对象 import { b, lib } from "lib"; const x = lib("test"); const y = b(123);
简化写法(仅CJS优先场景)
如果你的库不需要支持ESM环境下直接导入顶层单个成员(如import {b} from 'lib'),仅需要支持默认导入和CJS的require用法,可以用更简洁的export =语法:
declare function lib(input: string): number; declare namespace lib { export function b(num: number): string; export const version: string; } export = lib;
该写法需配合tsconfig中esModuleInterop: true使用,即可同时支持CJS的const lib = require('lib')和ESM的import lib from 'lib'用法。
内容的提问来源于stack exchange,提问作者Coderer
相关产品推荐
相关产品推荐

