仅当映射到它的类型未定义时,我们如何才能使 arg 成为可选的?
How can we make an arg be optional only if the type mapped to it is undefined?
例如,如果我们有下面的代码,
type Events = {
SOME_EVENT: number
OTHER_EVENT: string
ANOTHER_EVENT: undefined
}
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 ) {}
有效 (playground link),我们怎样才能使发出调用不需要 ANOTHER_EVENT
事件的第二个参数?
例如,我可以添加以下行并且它有效:
emitter.emit('OTHER_EVENT', 'foo')
但是如果我想用 'ANOTHER_EVENT'
调用 emit
,我想在没有第二个参数的情况下进行:
emitter.emit('ANOTHER_EVENT') // ERROR, expected 2 arguments, but got 1.
这会给出错误,因为它需要第二个参数。 (playground link)
为了让它工作,我必须写:
emitter.emit('ANOTHER_EVENT', undefined)
我们如何才能使第二个参数仅在我们用 'ANOTHER_EVENT'
调用 emit
的情况下才需要?
您可以使用 ?
:
使第二个参数可选
type Events = {
SOME_EVENT: number
OTHER_EVENT: string
ANOTHER_EVENT?: undefined
}
interface EventEmitter<EventTypes> {
on<K extends keyof EventTypes>(s: K, listener: (v: EventTypes[K]) => void);
emit<K extends keyof EventTypes>(s: K, v?: EventTypes[K]);
}
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) {}
emitter.emit('OTHER_EVENT', 'foo')
emitter.emit('ANOTHER_EVENT')
根据第一个参数的输入,我认为不可能让它成为可选的。在那种情况下,您只需要两种不同的方法。
您可以在剩余参数中使用元组来根据第一个参数更改参数的数量(甚至它们的可选性)。
type Events = {
SOME_EVENT: number
OTHER_EVENT: string
ANOTHER_EVENT: undefined
}
type EventArgs<EventTypes, K extends keyof EventTypes> = EventTypes[K] extends undefined ?[]:[EventTypes[K]]
interface EventEmitter<EventTypes> {
on<K extends keyof EventTypes>(s: K, listener: (...v: EventArgs<EventTypes,K>) => void);
emit<K extends keyof EventTypes>(s: K, ...v: EventArgs<EventTypes,K>);
}
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) {}
emitter.emit('OTHER_EVENT', 'foo')
emitter.emit('ANOTHER_EVENT')
例如,如果我们有下面的代码,
type Events = {
SOME_EVENT: number
OTHER_EVENT: string
ANOTHER_EVENT: undefined
}
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 ) {}
有效 (playground link),我们怎样才能使发出调用不需要 ANOTHER_EVENT
事件的第二个参数?
例如,我可以添加以下行并且它有效:
emitter.emit('OTHER_EVENT', 'foo')
但是如果我想用 'ANOTHER_EVENT'
调用 emit
,我想在没有第二个参数的情况下进行:
emitter.emit('ANOTHER_EVENT') // ERROR, expected 2 arguments, but got 1.
这会给出错误,因为它需要第二个参数。 (playground link)
为了让它工作,我必须写:
emitter.emit('ANOTHER_EVENT', undefined)
我们如何才能使第二个参数仅在我们用 'ANOTHER_EVENT'
调用 emit
的情况下才需要?
您可以使用 ?
:
type Events = {
SOME_EVENT: number
OTHER_EVENT: string
ANOTHER_EVENT?: undefined
}
interface EventEmitter<EventTypes> {
on<K extends keyof EventTypes>(s: K, listener: (v: EventTypes[K]) => void);
emit<K extends keyof EventTypes>(s: K, v?: EventTypes[K]);
}
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) {}
emitter.emit('OTHER_EVENT', 'foo')
emitter.emit('ANOTHER_EVENT')
根据第一个参数的输入,我认为不可能让它成为可选的。在那种情况下,您只需要两种不同的方法。
您可以在剩余参数中使用元组来根据第一个参数更改参数的数量(甚至它们的可选性)。
type Events = {
SOME_EVENT: number
OTHER_EVENT: string
ANOTHER_EVENT: undefined
}
type EventArgs<EventTypes, K extends keyof EventTypes> = EventTypes[K] extends undefined ?[]:[EventTypes[K]]
interface EventEmitter<EventTypes> {
on<K extends keyof EventTypes>(s: K, listener: (...v: EventArgs<EventTypes,K>) => void);
emit<K extends keyof EventTypes>(s: K, ...v: EventArgs<EventTypes,K>);
}
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) {}
emitter.emit('OTHER_EVENT', 'foo')
emitter.emit('ANOTHER_EVENT')