我正在从JavaScript开发过渡到强制TypeScript输入的雇主。我为包含典型$this->email = (property_exists($curl->response, 'email')) ? $curl->response->email : null;
的模型创建了Interface
。
我的同事提出了一些我认为可以理解的代码,但是它使用了这种嵌套的三元语句,使阅读变得混乱。
.on(event, handler)
这似乎是一种根据传入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
}
的{{1}}参数具有不同签名的方法。
这似乎正在工作,但是我想知道是否有另一种书写方式可以使它更容易阅读和理解。
答案 0 :(得分:1)
我会考虑使用映射接口并为其建立索引,因为在TypeScript中自然会根据对象类型为您提供“将字符串文字映射为特定类型”的操作。尽管您可以 使用条件类型来执行此操作,但它的确难以阅读和维护。
作为重构的第一步,我会做这样的事情:
// 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.on()
的{{1}}类型的event
参数到T
参数的映射。我们使用lookup types提取handler
类型的handler
。
也许可以进一步重构……例如,所有这些都是返回EventHandlerMap[T]
的函数,而第一个参数是void
;也许您可以使Model
仅跟踪不同事件之间的区别,然后使用更复杂的类型操作,但这可能比它值得的麻烦更多。
好的,希望能有所帮助;祝你好运!