export {} type F = ((a: string) => void) | ((b: boolean) => void) let f: F = (a: string) => {} f('foo') function f2 (f: F) { f('foo') ^^^^^ }
为什么光标处会出现这个错误呢?
[ts] Cannot invoke an expression whose type lacks a call signature. Type 'F' has no compatible call signatures.
PS. 唉头一次写 typescript 程序,碰到无数问题。typescript 要在本来无类型的 js 上面加类型搞出来的东西貌似比 java 的类型系统坑多(当然也灵活的多)
![]() | 1 kernel OP 额发现这里应该用&,才能得到正确的 overload 效果 |
![]() | 2 hst001 2018-10-01 20:04:17 +08:00 这个逻辑看起来就有问题吧,参数类型是 F,然后你就直接 f('foo'),编译器怎么知道你到时候传进来的 f 是 (a: string) => void 还是 (b: boolean) => void ? |
![]() | 3 kernel OP @hst001 F 是这二个函数 overload 在一起的效果,当然可以根据参数来自动判断 把 type F = ((a: string) => void) | ((b: boolean) => void) 改成 type F = ((a: string) => void) & ((b: boolean) => void) 就可以了 |
![]() | 6 hst001 2018-10-01 20:25:59 +08:00 @kernel #5 改成 & 表示取类型交集,换句话说,你等于告诉编译器,你传给 f2 的参数 f 是可以支持同时支持 string 和 boolean,所以就能编译通过了 |
8 VDimos 2018-10-01 22:49:18 +08:00 via Android ![]() 这个和重载不重载无关,联合类型并不是或的意思,它本身就是一个独立的类型,所以不能直接调用,它没有 call signature。如果你使用交叉类型,两个函数签名交叉类型依旧是函数,所以有 call signature,才能编译。交叉类型不应该用在函数上,这个产生的结果很抽象,应该用在对象上面。你这个类型应该把参数改为 string 和 boolean 的联合类型,而不是独立成两个函数再联合 |
![]() | 9 NickCarter 2018-10-01 23:27:33 +08:00 type F = (a: string | boolean) => void |
10 azh7138m 2018-10-01 23:58:28 +08:00 楼上的写法是更好的选择 关于重载,官方文档也有写示例,https://www.typescriptlang.org/docs/handbook/functions.html,可以写完声明,再去写具体的定义 |
![]() | 11 kernel OP ![]() @VDimos &用在多个函数上就是表示的是重载的意思吧。把参数改成 string | boolean 不是个办法,因为可能不同函数参数个数不一样 |
12 VDimos @kernel &用在函数上很抽象,我在官方文档里也没看见关于这个的讲解。你甚至可以在后面&一个任何类型,在编译时都会当作它有 call signature,但是实际上并没有 |
![]() | 13 kernel OP @VDimos 我是在搜 issue 列表发现&用在函数上就表示重载(而且不用&还真没有别的办法)。至于为什么一个函数可以&一个非函数而不报错,这可能是 ts 的缺陷吧。 |
![]() | 14 franklinyu 2018-10-03 10:50:36 +08:00 「搜 issue 列表发现&用在函数上就表示重载」真的?哪个 issue ?很有兴趣知道 |
![]() | 15 kernel OP |
16 vsomeone 2018-10-03 13:47:06 +08:00 不太懂这个重载是怎么写的… TypeScript 里的重载应该是下面这样吧 ```typescript class Person {} class Pet {} class Shop {} type Shopping = { (a: Person): void; (b: Pet, c: Shop): void; }; let shop: Shopping = (a?: Person, b?: Pet, c?: Shop) => { if (a instanceof Person) {} else if (b instanceof Pet && c instanceof Shop) {} } ``` |