仅当映射到它的类型未定义时,如何才能使arg为可选? [英] How can we make an arg be optional only if the type mapped to it is undefined?

查看:94
本文介绍了仅当映射到它的类型未定义时,如何才能使arg为可选?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如,如果我们有以下代码,

For example, if we have the following code,

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 ) {}

有效(

which works (playground link), how can we make it so that calls to emit do not require the second arg for the ANOTHER_EVENT event?

例如,我可以添加以下行,它可以正常工作:

For example, I can add the following line and it works:

emitter.emit('OTHER_EVENT', 'foo')

(但是,如果我想用'ANOTHER_EVENT'调用emit,我想在没有第二个arg的情况下执行此操作:

But if I want to call emit with 'ANOTHER_EVENT', I'd like to do it without the second arg:

emitter.emit('ANOTHER_EVENT') // ERROR, expected 2 arguments, but got 1.

给出错误,因为它需要第二个arg. (

which gives an error because it expects the second arg. (playground link)

要使其正常运行,我必须写:

To make it work, I have to write:

emitter.emit('ANOTHER_EVENT', undefined)

(仅在用'ANOTHER_EVENT'调用emit的情况下,如何才能使第二个arg不是必需的?

How can we make the second arg not required only for the case where we call emit with 'ANOTHER_EVENT'?

推荐答案

您可以在rest参数中使用元组,以基于第一个参数更改参数的数量(甚至是可选性).

You can use tuples in rest arguments to change the number of arguments (and even their optionality) based on the first argument.

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')

这篇关于仅当映射到它的类型未定义时,如何才能使arg为可选?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆