У меня есть следующий рабочий код без ошибок типа:
type Events = { SOME_EVENT: number; OTHER_EVENT: string }
interface EventEmitter<EventTypes> {
on<K extends keyof EventTypes>(s: K, listener: (v: EventTypes[K]) => void);
}
declare const emitter: EventEmitter<Events>;
emitter.on('SOME_EVENT', (payload) => testNumber(payload));
emitter.on('OTHER_EVENT', (payload) => testString(payload));
function testNumber( value: number ) {}
function testString( value: string ) {}
Однако я хотел бы использовать что-то похожее на enum
, чтобы иметь автозаполнение имен типов, чтобы я мог написать что-то вроде следующего вместо использования строковых литералов:
emitter.on(EventNames.SOME_EVENT, (payload) => testNumber(payload));
emitter.on(EventNames.OTHER_EVENT, (payload) => testString(payload));
Я пытаюсь сохранить вещи сухими, поэтому мне интересно, есть ли способ заставить это работать, не повторяя все имена событий в новом типе.
В простом JavaScript я могу легко сделать следующее:
const EventNames = [
'SOME_EVENT',
'OTHER_EVENT',
]
const Events = {}
for (const eventName of Events) {
Events[eventName] = eventName
}
// then use it:
emitter.on(Events.SOME_EVENT, (payload) => testNumber(payload));
emitter.on(Events.OTHER_EVENT, (payload) => testString(payload));
Таким образом, в простом JS я могу создавать объекты, подобные перечислению, без необходимости прибегать к чему-то менее СУХОМУ, например
const Events = {
SOME_EVENT: 'SOME_EVENT', // repeats the names twice
OTHER_EVENT: 'OTHER_EVENT',
}
emitter.on(Events.SOME_EVENT, (payload) => testNumber(payload));
emitter.on(Events.OTHER_EVENT, (payload) => testString(payload));
Мне интересно, как я могу сохранить вещи как можно более сухими в TypeScript, только когда-либо определяя имя каждого события только один раз, но также имея тип, связанный с полезными нагрузками события.
Я могу сделать это следующим менее сухим способом, повторяя названия событий по три раза каждое:
type Events = { SOME_EVENT: number; OTHER_EVENT: string }
const EventNames: {[k in keyof Events]: k} = {
SOME_EVENT: 'SOME_EVENT', OTHER_EVENT: 'OTHER_EVENT'
}
interface EventEmitter<EventTypes> {
on<K extends keyof EventTypes>(s: K, listener: (v: EventTypes[K]) => void);
}
declare const emitter: EventEmitter<Events>;
emitter.on(EventNames.SOME_EVENT, (payload) => testNumber(payload));
emitter.on(EventNames.OTHER_EVENT, (payload) => testString(payload));
function testNumber( value: number ) {}
function testString( value: string ) {}
Итак, мой вопрос: есть ли способ написать это так, чтобы я указывал события только один раз каждое, а также типы полезной нагрузки?
Если это невозможно сделать только с одним экземпляром каждого имени события, как лучше всего?
EventTypes
былtype
. Ваш ответ кажется лучшим вариантом. - person SLaks   schedule 30.11.2018