TypeScript中类包装函数的泛型类型注解实现方案
为泛型函数
wrapIt添加TypeScript类型注解 问题背景
现有如下类:
class Foo { static actions = ["func1", "func2"]; a: number; func1(str: string) { }; func2(n: number) { }; func3() {} }
需要实现泛型函数wrapIt,接收任意包含静态字段actions的类,返回一个仅实现actions中指定方法的包装类。当前JavaScript实现可正常运行,但TypeScript无法识别返回类的方法:
function wrapIt(MyClass) { return class { constructor() { for (const actionName of MyClass.actions) { const fn = MyClass.prototype[actionName]; this[actionName] = (...args: any[]) => { console.log("do something here that just call the original function"); return fn.bind(this)(...args); } } } } } const NewClass = wrapIt(Foo) const c = new NewClass(); c.func1("ok"); // TypeScript错误:无法识别func1
解决方案
通过TypeScript泛型与类型提取能力,为wrapIt添加精确的类型注解:
type ExtractActionMethods< T extends { actions: readonly string[] }, Actions = T["actions"][number] > = { [K in Actions]: K extends keyof T ? T[K] : never; }; function wrapIt<T extends { actions: readonly string[] }>( MyClass: T ): new () => ExtractActionMethods<T> { return class { constructor() { for (const actionName of MyClass.actions) { const fn = MyClass.prototype[actionName] as (...args: any[]) => any; this[actionName as keyof this] = (...args: any[]) => { console.log("do something here that just call the original function"); return fn.bind(this)(...args); }; } } } as unknown as new () => ExtractActionMethods<T>; } // 使用示例 const NewClass = wrapIt(Foo); const c = new NewClass(); c.func1("ok"); // 类型检查通过 c.func2(123); // 类型检查通过 // c.func3(); // 报错,符合预期:func3不在actions列表中
关键类型逻辑说明
ExtractActionMethods类型工具:先提取类静态actions字段中的所有方法名,再从原类实例类型中提取这些方法的类型,最终构建出包装类的实例类型- 泛型约束
T extends { actions: readonly string[] }:确保传入的类必须包含静态actions数组,避免非法入参 - 类型断言:由于动态添加方法时TypeScript无法自动推断类型,通过
as unknown as new () => ExtractActionMethods<T>将返回类断言为正确的构造函数类型
内容的提问来源于stack exchange,提问作者Guid
相关产品推荐
相关产品推荐

