Typescript类型扩展中的嵌套三元条件

Typescript类型扩展中的嵌套三元条件,typescript,interface,extends,Typescript,Interface,Extends,我正在从JavaScript开发过渡到一个强制执行类型脚本输入的雇主。我为一个模型创建了一个接口,该模型包含一个典型的。on(事件,处理程序) 我的同事提出了一些我认为可以理解的代码,但它使用了这个嵌套的三元语句,这使得阅读起来很混乱 interface Model { ... on<T extends "added" | "failed" | "initialized" | "changed" | "removed"> ( event: T,

我正在从JavaScript开发过渡到一个强制执行类型脚本输入的雇主。我为一个模型创建了一个
接口
,该模型包含一个典型的
。on(事件,处理程序)

我的同事提出了一些我认为可以理解的代码,但它使用了这个嵌套的三元语句,这使得阅读起来很混乱

interface Model {
    ...
    on<T extends "added" | "failed" | "initialized" | "changed" | "removed"> (
        event: T,
        handler: T extends "changed" | "removed"
                 ? (T extends "changed"
                     ? (model: Model, entity: Entity, data: object) => void
                     : (model: Model, id: string) => void)
                 : (model: Model, entity: Entity) => void,
        context?: object
    ): void
}

接口模型{
...
在(
事件:T,
处理程序:T扩展“已更改”|“已删除”
?(T扩展“已更改”
?(模型:模型,实体:实体,数据:对象)=>void
:(model:model,id:string)=>void)
:(模型:模型,实体:实体)=>void,
上下文?:对象
):无效
}
这似乎是一种为
处理程序
参数提供不同签名的方法,该参数是根据
事件
传入的


它似乎在工作,但我想知道是否有一种不同的模式来写这篇文章,这样就更容易阅读和理解了。

< P>我会考虑使用一个映射接口和索引,因为在一个“对象类型”中,“映射字符串到特定类型”的操作自然给了你。虽然您可以使用条件类型来实现这一点,但它确实更难读取和维护

作为重构的第一步,我会这样做:

// use a mapping from event name to event handler type
interface EventHandlerMap {
  added: (model: Model, entity: Entity) => void;
  failed: (model: Model, entity: Entity) => void;
  initialized: (model: Model, entity: Entity) => void;
  changed: (model: Model, entity: Entity, data: object) => void;
  removed: (model: Model, id: string) => void;
}

interface Model {
  on<T extends keyof EventHandlerMap>(
    event: T,
    handler: EventHandlerMap[T], // index into the mapping
    context?: object
  ): void;
}
//使用从事件名称到事件处理程序类型的映射
接口EventHandlerMap{
增加:(模型:模型,实体:实体)=>作废;
失败:(模型:模型,实体:实体)=>作废;
已初始化:(模型:模型,实体:实体)=>作废;
更改:(模型:模型,实体:实体,数据:对象)=>作废;
删除:(model:model,id:string)=>void;
}
界面模型{
在(
事件:T,
handler:EventHandlerMap[T],//索引到映射中
上下文?:对象
):无效;
}
您可以说服自己它的行为方式是相同的(或者使用代码末尾的链接查看)。
EventHandlerMap
界面只是一个帮助器,您实际上并没有将其分配给任何对象。但是它描述了从
Model.on()
类型
T
事件
参数到
处理程序
参数的映射。我们使用将
处理程序
类型作为
EventHandlerMap[T]
拉出

有可能进一步重构此。。。例如,所有这些都是返回
void
的函数,第一个参数是
Model
;也许您可以让
EventHandlerMap
只跟踪不同事件之间的差异,然后使用更复杂的类型操作,但这可能会带来更多麻烦

好吧,希望这会有帮助;祝你好运


是否还有另一个Stack Exchange网络站点更适合问这个问题?我可能会索引到映射接口,而不是在这里使用嵌套条件;如果在我接触到真正的电脑之前没有人到这里,我会发布一个答案。感谢您周到的回复。我认为您正在使用mapper界面,使用
keyof
链接
事件
处理程序
方法对我来说很有意义。我喜欢它提供了灵活性,可以根据需要以代码其余部分熟悉的样式添加新映射。我同意进一步重构以减少冗余可能有些过分,而这对于其他重载语言来说更为自然。感谢您的时间和反馈。