请教一个 typescript 的类型问题 - V2EX
This topic created in 2781 days ago, the information mentioned may be changed or developed.
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 的类型系统坑多(当然也灵活的多)

16 replies    2018-10-03 13:47:06 +08:00
kernel
    1
kernel  
OP
   Oct 1, 2018
额发现这里应该用&,才能得到正确的 overload 效果
hst001
    2
hst001  
   Oct 1, 2018
这个逻辑看起来就有问题吧,参数类型是 F,然后你就直接 f('foo'),编译器怎么知道你到时候传进来的 f 是 (a: string) => void 还是 (b: boolean) => void ?
kernel
    3
kernel  
OP
   Oct 1, 2018
@hst001 F 是这二个函数 overload 在一起的效果,当然可以根据参数来自动判断
把 type F =
((a: string) => void) |
((b: boolean) => void)
改成
type F =
((a: string) => void) &
((b: boolean) => void)

就可以了
kernel
    4
kernel  
OP
   Oct 1, 2018   1
话说 typescript 开始起飞了,不建一个节点吗,毕竟和 js 还是完全不同的 @livid
kernel
    5
kernel  
OP
   Oct 1, 2018
@hst001 你说的是,用 | 的话是不知道传进来的具体是哪个,因为它不是重载函数了
hst001
    6
hst001  
   Oct 1, 2018
@kernel #5 改成 & 表示取类型交集,换句话说,你等于告诉编译器,你传给 f2 的参数 f 是可以支持同时支持 string 和 boolean,所以就能编译通过了
kernel
    7
kernel  
OP
   Oct 1, 2018
@hst001 对,&才是函数重载,之前以为是|
VDimos
    8
VDimos  
   Oct 1, 2018 via Android   1
这个和重载不重载无关,联合类型并不是或的意思,它本身就是一个独立的类型,所以不能直接调用,它没有 call signature。如果你使用交叉类型,两个函数签名交叉类型依旧是函数,所以有 call signature,才能编译。交叉类型不应该用在函数上,这个产生的结果很抽象,应该用在对象上面。你这个类型应该把参数改为 string 和 boolean 的联合类型,而不是独立成两个函数再联合
NickCarter
    9
NickCarter  
   Oct 1, 2018
type F = (a: string | boolean) => void
azh7138m
    10
azh7138m  
   Oct 1, 2018
楼上的写法是更好的选择
关于重载,官方文档也有写示例,https://www.typescriptlang.org/docs/handbook/functions.html,可以写完声明,再去写具体的定义
kernel
    11
kernel  
OP
   Oct 2, 2018   1
@VDimos &用在多个函数上就是表示的是重载的意思吧。把参数改成 string | boolean 不是个办法,因为可能不同函数参数个数不一样
VDimos
    12
VDimos  
   Oct 2, 2018
@kernel &用在函数上很抽象,我在官方文档里也没看见关于这个的讲解。你甚至可以在后面&一个任何类型,在编译时都会当作它有 call signature,但是实际上并没有
kernel
    13
kernel  
OP
   Oct 2, 2018
@VDimos 我是在搜 issue 列表发现&用在函数上就表示重载(而且不用&还真没有别的办法)。至于为什么一个函数可以&一个非函数而不报错,这可能是 ts 的缺陷吧。
franklinyu
    14
franklinyu  
   Oct 3, 2018
「搜 issue 列表发现&用在函数上就表示重载」真的?哪个 issue ?很有兴趣知道
vsomeone
    16
vsomeone  
   Oct 3, 2018
不太懂这个重载是怎么写的… 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) {}
}

```
About     Help     Advertise     Blog     API     FAQ     Solana     5162 Online   Highest 6679       Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 97ms UTC 05:41 PVG 13:41 LAX 22:41 JFK 01:41
Do have faith in what you're doing.
ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86