Я бы подумал об использовании интерфейса отображения и индексации в нем, поскольку операция «преобразование строкового литерала в определенный тип» естественным образом предоставляется вам в 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()
event
типа T
в параметр handler
.И мы используем типы поиска , чтобы извлечь тип handler
как EventHandlerMap[T]
.
Может быть возможно провести дальнейший рефакторинг этого ... например, все эти функции возвращают void
, а первый параметр - Model
;возможно, вы могли бы заставить EventHandlerMap
только отслеживать, что отличается между различными событиями, а затем использовать более сложные типы манипуляций, но это может быть больше проблем, чем оно того стоит.
Хорошо, надеюсь, это поможет;удачи!
Ссылка на код