我正在尝试完成与
C#
类似的行为。在 C#
中,我可以使用反射来动态实例化基于 Type
类的类。下面的代码展示了如何在c#
中进行操作,相当简单:
interface IHandler
{
void Handle();
}
var handlers = new Dictionary<string, Type>
{
{ "querydom", typeof(QueryDomHandler) },
{ "other", typeof(OtherHandler) },
};
var type = handlers["querydom"];
var instance = (IHandler)Activator.CreateInstance(type, args);
instance.Handle();
如何使用
typescript
实现同样的效果?我绘制了以下代码,但我不知道如何从类中获取“类型”(QueryDomCommandHandler
),或者如何在不使用类名称的情况下动态实例化类( new QueryDomCommandHandler()
)。
let handlers = [];
handlers[CommandType.QueryDom] = QueryDomCommandHandler; //how to store the "type"?
chrome.runtime.onMessage.addListener((message: Command, sender, sendResponse) => {
logger.debug(`${isFrame ? 'Frame' : 'Window'} '${document.location.href}' received message of type '${CommandType[message.command]}'`);
const handlerType = handlers[CommandType.QueryDom];
const handlerInstance = ????? //how to instantiate the class?
if (message.command == CommandType.QueryDom) {
const handler = new QueryDomCommandHandler(message as RulesCommand);
const response = handler.handle();
sendResponse(response);
return true;
}
else if (message.command == CommandType.Highlight) {
const handler = new HighlightCommandHandler(message as RulesCommand);
handler.handle();
}
});
有什么见解吗?
更新
感谢您的回答,这是我的解决方案,虽然我想使用
enum
而不是 Record
中的硬编码字符串,但无法弄清楚:
const handlers: Record<string, (new () => commands.CommandHandlerBase)> = {
'QueryDom': QueryDomCommandHandler,
'Highlight': HighlightCommandHandler,
'ClearHighlight': ClearHighlightCommandHandler,
};
const handlerType = handlers[commands.CommandType[message.command]];
const handler = new handlerType();
const response = await handler.handle(message);
注意:你无法在打字稿中获取“类型”,因为该类型在运行时不存在,你得到的实际上是类的构造函数。
您首先需要在handlers
数组上输入某种类型才能进行推理:
let handlers: (new (...arg: any[]) => CommandHandler)[] = [];
将获取构造函数后创建实例,只需
CommandHandler
部分修改为处理程序基类的名称
new
即可,类名本身并不重要:
const handlerInstance = new handlerType()
// ^? const handlerInstance: CommandHandler