我正在开发一个类来自动为 Express 创建路由并调用控制器中的函数。但是,当我尝试执行
this[methodName](req, res)
时,我遇到错误消息:“元素隐式具有“任意”类型,因为“字符串”类型的表达式不能用于索引“AbstractActionController”类型。在类型“AbstractActionController”.ts(7053) 上找不到带有“字符串”类型参数的索引签名。我已经广泛搜索了答案,但还没有找到。我相信我需要指定类型,但我不确定如何这样做。
import AbstractActionControllerInterface from './interfaces/AbstractActionControllerInterface'
import { Application, Request, Response } from 'express'
class AbstractActionController implements AbstractActionControllerInterface {
public alias: string
private app: Application
constructor(alias: string, app: Application) {
this.alias = alias === 'index' ? '' : alias
this.app = app
this.registerActionRoutes()
}
/**
* registerActionRoutes
*
* Called to log the routes with Action indicator in a controller.
*/
private registerActionRoutes() {
const classMethods = Object.getOwnPropertyNames(
Object.getPrototypeOf(this),
)
for (const methodName of classMethods) {
if (methodName !== 'constructor' && methodName.includes('Action')) {
let route = methodName.split('Action')[0]
route = route === 'index' ? '' : route
this.app.all(
`${this.alias}/${route}`,
(req: Request, rep: Response) => {
if (typeof this[methodName] === 'function') {
this[methodName](req, rep)
}
},
)
console.log(
`[Lua]\x1b[33m Route ${this.alias}/${route} attached. \x1b[0m`,
)
}
}
}
}
export default AbstractActionController
我尝试使用 [key: string]: 任何类型,但是 this 没有索引🤔🤔也许是我不知道的东西。
您可以使用类型谓词来缩小操作函数的类型(类型谓词以前称为用户定义的类型防护)。
这是最简单的版本,会缩小你的功能:
function isActionFunction(fn: any): fn is (req: Request, res: Response) => void {
return typeof fn === 'function';
}
这是代码的更新版本,显示了其在上下文中的用法:
import { Application, Request, Response } from 'express'
function isActionFunction(fn: any): fn is (req: Request, res: Response) => void {
return typeof fn === 'function';
}
class AbstractActionController {
public alias: string
private app: Application
constructor(alias: string, app: Application) {
this.alias = alias === 'index' ? '' : alias
this.app = app
this.registerActionRoutes()
}
/**
* registerActionRoutes
*
* Called to log the routes with Action indicator in a controller.
*/
private registerActionRoutes() {
const classMethods = Object.getOwnPropertyNames(
Object.getPrototypeOf(this),
) as Array<keyof typeof this & string>;
for (const methodName of classMethods) {
if (methodName.endsWith('Action')) {
let route = methodName.split('Action')[0]
route = route === 'index' ? '' : route
this.app.all(
`${this.alias}/${route}`,
(req: Request, rep: Response) => {
const fn = this[methodName];
if (isActionFunction(fn)) {
fn(req, rep)
}
},
)
console.log(
`[Lua]\x1b[33m Route ${this.alias}/${route} attached. \x1b[0m`,
)
}
}
}
}
export default AbstractActionController