I'm not getting the result I expected from narrowing on a union type. Here's a snippet which captures the issue:
interface A {
a : number;
}
interface B {
b : string;
}
const isAnA = (arg : A | B) : arg is A => {
return "a" in arg;
}
const applyFunc = <T>(func : (x : T) => number, arg : T) => {
return func(arg)
}
const doTheThing = (arg : A | B) => {
let f;
if (isAnA(arg)) {
f = (x : A) => x.a * 2;
} else {
f = (x : B) => parseInt(x.b) * 2;
}
return applyFunc(f, arg);
}
What I expected to happen here was that the isAnA()
typeguard would let the compiler know that f
has type (x : A) => number
if arg
is an A
, and type (x : B) => number
if arg
is a B
, allowing applyFunc
to be called on arg
and f
together.
However, I get this from the compiler:
Type '(x: B) => number' is not assignable to type '(x: A) => number'.
Types of parameters 'x' and 'x' are incompatible.
Property 'b' is missing in type 'A' but required in type 'B'.
Is there any way to get this working other than explicitly typeguarding the call to applyFunc
?