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

时间:2019-06-29 16:28:52

标签: typescript interface extends

我正在从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}}参数具有不同签名的方法。

这似乎正在工作,但是我想知道是否有另一种书写方式可以使它更容易阅读和理解。

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仅跟踪不同事件之间的区别,然后使用更复杂的类型操作,但这可能比它值得的麻烦更多。

好的,希望能有所帮助;祝你好运!

Link to code