TypeScript: Union of function signatures cannot be invoked because it lacks a call signature
Reduced test case:
var foo: ((arg: string) => void) | ((arg: any) => void);
foo(null);
- With 1.5.3, this compiles fine. With 1.6-beta, this gives
error TS2349: Cannot invoke an expression whose type lacks a call signature.
null is assignable to both string and any so it should compile. - Maybe related - getting quickinfo for foo on the second line does throw an error
TypeError: Cannot read property 'flags' of undefined
in playground even though it compiles fine with 1.5.3. I didn’t try quickinfo on 1.6 - If foo was
((arg: string) => void) | ((arg: number) => void);
(number instead of any in the second signature) then both 1.5.3 and 1.6 give that error, even though again null is assignable to both.
For motivation, the original code is https://github.com/Arnavion/libjass/blob/6606413/src/utility/promise.ts#L363 (the error is on handler). It’s an implementation of the ES6 promise spec, specifically http://www.ecma-international.org/ecma-262/6.0/#sec-promisereactionjob - handler would be either the fulfilled callback or rejected callback and the argument passed to it would be either the resolution value or the rejection reason accordingly, hence its signature.
(I understand it would be more type-safe to have separate handlers for the two cases with one signature each from the union, but that complicates the implementation slightly.)
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Reactions: 2
- Comments: 15 (8 by maintainers)
Hmmm. A scenario like following still throws this error in 1.8.7, which doesn’t seem like it should:
However if making it more permissive:
or restricted:
fixes the error.
It seems this is still an issue in TS 2.4.2
This fixes the error:
I am running into this in 2.6.2, it seems odd to me that this doesn’t work. Is this working as intended?
Here’s pretty simple example:
I am getting around it currently by casting to an interface with the “correct” union.
@dkoprowski You want
(bar.handler as A)(false)