Reputation: 444
Why is the following TypeScript code invalid?
type A = { kind: "a" }
type B = { kind: "b" }
const a = (a: A): void => undefined
const b = (b: B): void => undefined
const c = <C extends A | B>(c: C): void => (c.kind == "a" ? a(c) : b(c))
It looks like TypeScript cannot figure out that after c.kind == "a"
, c
is an A
. Why not?
The following variant seems to be working.
type A = { kind: "a" }
type B = { kind: "b" }
type C = A | B
const a = (a: A): void => undefined
const b = (b: B): void => undefined
const c = (c: C): void => (c.kind == "a" ? a(c) : b(c))
Upvotes: 2
Views: 51
Reputation: 250056
A typeguard will work on a parameter of a union type, it will not work on a generic type parameter that extends a union. This is documented in this issue. The issue is open and might get fixed at a later date.
A possible work-around for this issue is to use your non-generic version, which for your simple example will work just the same.
If your signature is more complicated and you use the generic types in some other capacity (for example in some conditional types, or to create a relation between other parameter or parameters and return types) you can use a function with multiple signatures, a public generic signature and an non-generic implementation signature:
function c<C extends A | B>(c: C): void
function c(c: A | B): void {
return c.kind == "a" ? a(c) : b(c);
}
Upvotes: 2