Keigo Imai
Keigo Imai

Reputation: 155

Calling unions of function types in TypeScript

In TypeScript 3.0.3, The following code will give a compile-time error:

function f() {
    if (true) {
        return (x: {left:String}) => x.left;
    } else {
        return (x: {right:String}) => x.right;
    }
}

class C {
    left: String = "";
    right: String = "";
}

f()(new C());

code at typescriptlang.org

I expected that the type of f would be function f(): {left:String; right:String} => String or equivalent one (for example, Scala typechecker reports a type like this).

However, I got the following type error:

./leftright.ts:17:1 - error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '((x: { left: String; }) => String) | 
((x: { right: String; }) => String)' has no compatible call signatures.

17 f()(new C());

It seems that unions of function types are not directly callable, despite we can refer to a field in a union of object types.

Is there any way to modify f() to a callable one while preserving if-statement inside it?

Upvotes: 0

Views: 435

Answers (1)

Matt McCutchen
Matt McCutchen

Reputation: 30919

Just annotate the return type of f, and the compiler will see that each of the functions you are returning is compatible with that type:

function f(): (x: { left: String, right: String }) => String {
    if (true) {
        return (x: {left:String}) => x.left;
    } else {
        return (x: {right:String}) => x.right;
    }
}

Upvotes: 1

Related Questions