Typescript 将两种类型关联在一起

Typescript 将两种类型关联在一起,typescript,typescript-generics,Typescript,Typescript Generics,我有一些实现命令模式的代码 type=Function&{prototype:T} 导出类命令总线{ 私有处理程序=新映射() 私有defaultHandler:Handler=(命令)=>{ 抛出新错误(`No handler registed for type${command.constructor.name}`) } 构造函数(只读目标:上下文){} 处理( commandType:Type, 处理者:处理者, ) { this.handlers.set(commandType,hand

我有一些实现命令模式的代码

type=Function&{prototype:T}
导出类命令总线{
私有处理程序=新映射()
私有defaultHandler:Handler=(命令)=>{
抛出新错误(`No handler registed for type${command.constructor.name}`)
}
构造函数(只读目标:上下文){}
处理(
commandType:Type,
处理者:处理者,
) {
this.handlers.set(commandType,handler)
还这个
}
do(命令:命令){
const handler=this.handlers.get(command.constructor)| | this.defaultHandler
返回处理程序(this.target,命令)
}
}
导出接口处理程序{
(目标:上下文,命令:HandledCommand):结果
}
它的测试是,正在使用的一些其他示例是和

我对typescript非常陌生,我不知道的是如何对命令(在这个模式的CQRS-ish实现中,它基本上只是一条消息)和预期结果类型之间的关联进行建模

目前,我们必须指定返回类型,正如我们所做的那样,但我觉得这可能会被烘焙到命令的类型中,并由此暗示处理程序的返回类型)


我想我可能需要使用元组类型,这样一个命令不仅定义为
GetRefs
或其他类型,而且定义为
[GetRefs,Promise
。我不确定在哪里或如何执行此操作。

也许您可以执行以下操作:

class CommandBus<T, C extends { constructor: Function }, M extends [C, any] = never> {
    private handlers = new Map<Function, Function>()
    private defaultHandler: Handler<T, C> = (_, command) => {
        throw new Error(`No handler registered for commands of type ${command.constructor.name}`)
    }

    constructor(readonly target: T) { }

    handle<H extends C, R>(
        commandType: Type<H>,
        handler: Handler<T, H, R>,
    ): CommandBus<T, C, M | [H, R]> {
        this.handlers.set(commandType, handler)
        return this;
    }

    do<H extends M[0]>(command: H): Extract<M, [H, any]>[1] {
        const handler = this.handlers.get(command.constructor) || this.defaultHandler
        return handler(this.target, command)
    }
}
在这里,我正在进行方法链接,这样我唯一拥有名称的
CommandBus
实例就是已经设置好处理
Date
RegExp
值的实例

const d = b.do(new Date()).toUpperCase(); // string
console.log(d); // 2020 HELLO
const r = b.do(/hello/); // boolean
console.log(r); // true
我觉得不错。好吧,希望有帮助。祝你好运


据我所知,您正在寻找一种方法来更改
句柄

句柄(
commandType:Type,
handles命令,
):命令总线{
this.handlers.set(commandType,handler)
还这个
}

句柄(
handles命令,
):命令总线{
const commandType:Type=magic(处理程序)
this.handlers.set(commandType,handler)
还这个
}
是这样吗


如果是这样,简短的回答是“否”。您需要commandType对类对象的引用,以便在运行时用作处理程序的键。您可以从
handler
参数获取
commandType
的类型,但无法获取对类对象的引用

区别在于类型声明空间变量声明空间——更多关于中的内容


由于您无法从类型中获取类对象,因此对您的问题的任何回答都将相当于重新安排代码,以便以其他方式将类对象作为参数传入—但它仍需要以某种方式传入到对
句柄的每次调用。

这很好,几乎对我有效!我似乎缺少的东西,是传递
do
函数的能力,因为我无法确定如何获取该函数的动态创建类型签名并在其他地方使用它。例如,导致编译错误,因为
refs
的类型为
unknown
。由于该映射是在运行时定义的,因此在编译时不可用。您能否在实例化
命令总线
时定义所有处理程序?如果是这样,您可以使用对象将命令类型映射到处理程序来构造
命令总线
。然后您可能可以使用从该映射对象获取调用
do
的结果类型。我认为这是我的初始设置,您的答案让我不太明白为什么这不可能。谢谢!太好了!很高兴能帮上忙。现在你正在钻研一个更具体的问题,也许值得开始一个新的、更具体的问题。你可以提供几行示例,说明你想做什么但做不到。到你的github的链接有助于我们确定我知道你在寻找什么,但最好在问题中有关键片段(例如,你将
绑定到
执行
的片段)。好的,谢谢@alexanderbird的反馈。我对这个问题进行了更多的分解,并表达了第一个最基本的方面。
const d = b.do(new Date()).toUpperCase(); // string
console.log(d); // 2020 HELLO
const r = b.do(/hello/); // boolean
console.log(r); // true