如何导出模块接口对象的typedef类型?
如何为模块返回的对象定义可导入的类型?
假设我有一个名为foo的模块,包含bar和baz方法:
function foo(){ function bar() {} function baz() {} return { bar, baz } }
我希望定义该返回对象的类型,以便能在不同文件中导入。但@typedef只有处于文件全局作用域时才能被导入。
我自己想到一个能实现需求但可能对某些模块实现不够健壮的方法:
function foo(){ function bar() {} function baz() {} return { bar, baz } } let type = foo() // 创建一个任意实例 /** @typedef {type} foo */
请问是否有官方推荐的方式来定义模块接口对象的类型?另外,我认为在全局作用域手动编写整个对象的typedef并非好方案,因为每个方法的文档已经编写过一次了。
官方推荐的解决方案
1. 利用ReturnType自动推导类型(无需重复编写属性)
JSDoc支持通过ReturnType<typeof 函数名>自动推导函数返回值的类型,你可以在全局作用域基于这个推导结果定义类型:
function foo(){ /** * bar方法的详细文档 */ function bar() {} /** * baz方法的详细文档 */ function baz() {} return { bar, baz } } /** * @typedef {ReturnType<typeof foo>} FooType */
这个FooType是全局作用域的类型,可以在其他文件中通过/** @typedef {import('./your-module-path').FooType} FooType */导入使用,完全复用了内部方法已有的注释,不需要重复编写类型结构。
2. 全局@typedef结合@returns关联(适合需要显式定义类型的场景)
如果需要更清晰地展示类型结构,可以先在全局定义@typedef,然后在foo函数的@returns中关联它,同时复用内部方法的注释:
/** * @typedef {Object} FooType * @property {typeof bar} bar - 复用bar方法的文档:这里可以直接引用内部bar的类型和注释 * @property {typeof baz} baz - 复用baz方法的文档:同理引用内部baz的类型 */ /** * 创建FooType实例的工厂函数 * @returns {FooType} */ function foo(){ /** * bar方法的详细文档 */ function bar() {} /** * baz方法的详细文档 */ function baz() {} return { bar, baz } }
这种方式既保留了类型的显式定义,又避免了重复编写方法的文档,同时FooType可以被其他文件导入。
3. ES模块场景下直接导出类型
如果你的项目使用ES模块,可以直接导出类型定义,方便其他文件导入:
/** * @typedef {Object} FooType * @property {Function} bar - bar方法的文档描述 * @property {Function} baz - baz方法的文档描述 */ /** * @returns {FooType} */ export function foo(){ function bar() {} function baz() {} return { bar, baz } } // 导出类型供其他文件导入 export { FooType };
其他文件可以通过import { FooType } from './your-module'直接导入这个类型。
关于你当前方法的局限性
你通过实例化foo推导类型的方式在简单场景下可行,但存在几个问题:
- 如果
foo函数有初始化副作用、依赖外部状态,或者实例化成本高,这种方式会触发不必要的执行 - 如果
foo的返回值类型会根据输入参数变化,这种方式只能捕获当前实例的类型,无法覆盖所有可能的返回结构
内容的提问来源于stack exchange,提问作者Khaled
相关产品推荐
相关产品推荐

