实际上兼容的两个函数,为什么TypeScript报错“没有兼容的调用签名”?

自己实现了一个缩水版的EventTarget

interface MyEventTarget {
    addEventListener: (type: string, listener: EventListener) => void
}

但如果想和原生EventTarget混合使用的话:

function test(foo: MyEventTarget | EventTarget) {
    return foo.addEventListener('click', console.log);
}

会报错:无法调用类型缺少调用签名的表达式。类型“((type: string, listener: EventListener) => void) | ((type: string, listener: EventListener | Eve...”没有兼容的调用签名。

clipboard.png

如果强行拆开的话,却又可以:

function test(foo: MyEventTarget | EventTarget) {
    if (foo instanceof EventTarget) {
        return foo.addEventListener('click', console.log);
    }
    else {
        return foo.addEventListener('click', console.log);
    }
}
// OK

但是实在是太丑了。

所以请问一下大家:

  1. Is it a feature, or a bug?
  2. 不论是feature还是bug,类似的情形应该怎样优雅地处理?
阅读 11.9k
1 个回答

这是一个 bug ,目前还没有解决。

分开来处理也是一种解决方式,或者通过继承:

interface MyEventTarget extends EventTarget {
    addEventListener(
        type: string,
        listener: EventListener | EventListenerOrEventListenerObject,
        options?: boolean | AddEventListenerOptions
    ): void
}

function test(foo: MyEventTarget) {
    return foo.addEventListener('click', console.log);
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题