TypeScript类内通过字符串调用方法遇TS7053错误,求Express场景解决方案
解决TypeScript索引类型错误:无法用字符串索引AbstractActionController
错误原因
TypeScript无法确认methodName这个字符串对应的是类的有效方法成员,且由于你的类包含私有属性app,直接添加[key: string]: any索引签名会因为权限不兼容(索引签名是公共的,无法覆盖私有成员)而失效。
解决方案
方案一:调用时断言方法类型
在执行方法前,将methodName断言为类的键类型,并确保方法符合Express请求处理函数的签名:
修改路由回调部分的代码:
this.app.all( `${this.alias}/${route}`, (req: Request, rep: Response) => { // 将methodName断言为类的键类型 const actionMethod = this[methodName as keyof AbstractActionController]; // 验证是函数后,断言为Express请求处理函数类型并调用 if (typeof actionMethod === 'function') { (actionMethod as (req: Request, res: Response) => void)(req, rep); } }, );
方案二:提前断言方法列表类型
将获取到的类方法列表断言为Array<keyof AbstractActionController>,让TypeScript在循环时识别methodName是类的有效键:
修改registerActionRoutes方法:
private registerActionRoutes() { // 断言方法列表为类的键数组 const classMethods = Object.getOwnPropertyNames( Object.getPrototypeOf(this), ) as Array<keyof AbstractActionController>; for (const methodName of classMethods) { // 额外判断methodName是字符串(因为keyof可能包含symbol类型) if (methodName !== 'constructor' && typeof methodName === 'string' && methodName.includes('Action')) { let route = methodName.split('Action')[0]; route = route === 'index' ? '' : route; this.app.all( `${this.alias}/${route}`, (req: Request, rep: Response) => { const actionMethod = this[methodName]; if (typeof actionMethod === 'function') { (actionMethod as (req: Request, res: Response) => void)(req, rep); } }, ); console.log( `[Lua]\x1b[33m Route ${this.alias}/${route} attached. \x1b[0m`, ); } } }
方案三:约束接口的Action方法类型
如果你的AbstractActionControllerInterface需要明确约束Action方法,可以定义统一的方法类型:
import { Request, Response } from 'express'; // 定义Action方法的统一类型 type ActionHandler = (req: Request, res: Response) => void; interface AbstractActionControllerInterface { alias: string; // 允许任意后缀为Action的方法 [key: `${string}Action`]: ActionHandler; }
这种方式更严谨,但需要确保子类实现的所有Action方法都符合该类型。
内容的提问来源于stack exchange,提问作者Dayvson Spacca
相关产品推荐
相关产品推荐

