TypeScript中如何通过索引动态调用类原型方法?
解决TypeScript中动态调用类方法的类型问题
核心问题分析
你遇到的错误本质是:TypeScript默认把methods数组推断为string[],无法识别其中元素是类的方法键名;而用as keyof Foo时,又会包含类的非方法属性(比如示例里的ro),导致TypeScript认为可能拿到字符串类型,无法调用。
解决方案1:给方法列表添加精确类型
直接给methods指定类型,只保留类中方法的键名:
class Foo { readonly ro: string = ''; constructor() {} fn(s: number) { console.log(s); } anotherFn() { console.log('another'); } } const foo = new Foo(); // 提取Foo类中所有方法的键名类型 type FooMethodKeys = keyof Pick<Foo, { [K in keyof Foo]: Foo[K] extends Function ? K : never }[keyof Foo]>; // 约束数组只能存方法键名 const methods: FooMethodKeys[] = ['fn', 'anotherFn']; // 现在动态调用不会报错 for (const methodName of methods) { foo[methodName](0); // 若方法参数不同,需单独做类型判断 }
解决方案2:让类直接导出方法名列表
如果想让类提供可直接使用的类型化方法列表,可以通过静态属性实现:
// 通用工具类型:提取类中所有方法的键名 type MethodKeys<T> = keyof Pick<T, { [K in keyof T]: T[K] extends Function ? K : never }[keyof T]>; class Foo { readonly ro: string = ''; constructor() {} fn(s: number) { console.log(s); } anotherFn() { console.log('another'); } // 静态属性存储方法名,类型自动约束 static readonly methodNames: MethodKeys<Foo>[] = ['fn', 'anotherFn']; } const foo = new Foo(); // 直接用类导出的列表遍历调用 for (const methodName of Foo.methodNames) { if (methodName === 'fn') { foo[methodName](123); } else if (methodName === 'anotherFn') { foo[methodName](); } }
适配Playwright POM场景的用法
针对你的页面对象模型(POM)截图需求,可以这样实现:
type MethodKeys<T> = keyof Pick<T, { [K in keyof T]: T[K] extends Function ? K : never }[keyof T]>; class PageObject { constructor(private page: Page) {} async goToHome() { /* 页面跳转逻辑 */ } async openUserProfile() { /* 打开用户页逻辑 */ } async showSettings() { /* 打开设置页逻辑 */ } // 导出需要截图的方法列表 static readonly screenshotMethods: MethodKeys<PageObject>[] = [ 'goToHome', 'openUserProfile', 'showSettings' ]; } // 测试中遍历执行并截图 const page = await browser.newPage(); const pom = new PageObject(page); for (const methodName of PageObject.screenshotMethods) { await pom[methodName](); await page.screenshot({ path: `${methodName}.png` }); }
内容的提问来源于stack exchange,提问作者Mike
相关产品推荐
相关产品推荐

