TypeScript中IIFE封装模块的泛型类型导出方案咨询
解决方案
方案1:使用TS命名空间封装(最推荐)
你用IIFE的核心需求是隔离私有变量、区分公开导出内容,TypeScript原生命名空间完全可以满足这个需求,同时支持在同一作用域内定义值和类型,不需要把类型拆到顶层:
namespace Module { // 私有变量,模块外部完全无法访问,和IIFE的封闭效果一致 const G = "bar"; // 公开导出的函数值 export const F = <A>(x: A) => x; // 公开导出的同名泛型类型 export type F<A> = A; // 你的复杂类型定义可以放在这 } // 导出最终的同名值和类型,外部导入时可以直接使用 export const F = Module.F; export type F<A> = Module.F<A>;
外部使用效果完全符合预期:
import { F } from "./your-module"; // 作为函数使用 const num = F(123); // 类型为 number // 作为泛型类型使用 type StringType = F<string>; // 类型为 string
方案2:保留IIFE写法的兼容方案
如果你坚持要用IIFE的写法,可以通过显式声明IIFE返回值的携带类型,再从返回值中提取泛型类型,不需要把类型定义完全拆出IIFE:
const obj = (() => { const F = <A>(x: A) => x; const G = "bar"; type InternalF<A> = A; // 内部定义的泛型类型 return { F } as { F: typeof F; // 仅用于类型携带的标记属性,运行时无实际值 getType: <A>() => InternalF<A> }; })(); // 从返回值中提取泛型类型 export type F<A> = ReturnType<typeof obj.getType<A>>; export const F = obj.F;
这种写法可以保留你原有的IIFE编码习惯,唯一的额外开销是多了一个仅用于类型传递的标记属性,运行时不会产生实际影响。
内容的提问来源于stack exchange,提问作者Functor
相关产品推荐
相关产品推荐

