I'm struggling to make function overloads work properly in TypeScript.
My challenge involves a basic union type and a function that is capable of handling either type. I have defined overloads to deal with them separately.
type A = { type: "a", x: number }
type B = { type: "b", x: number, y: number }
type Z = A | B
function f(z: A): { x: number, y: undefined }
function f(z: B): {x: number, y: number}
function f(z: Z) {
if (z.type === "a") {
return {x: z.x, y: undefined}
} else {
return {x: z.x, y: z.y}
}
}
All seems to be functioning correctly.
// This works
const a = f({ type: "a", x: 1 })
const b = f({ type: "b", x: 1, y: 1 })
However, when attempting to use it with a distinct union type, the functionality breaks down.
// Why doesn't this work?
function g(z: Z) {
const x = f(z)
}
// This also doesn't work.
function h<T extends Z>(z: T) {
const x = f(z)
}
An error message crops up:
Argument of type 'Z' is not assignable to parameter of type 'B'.
Type 'A' is not assignable to type 'B'.
Property 'y' is missing in type 'A'.
This issue seems to stem from user error, but might also hint at a bug somewhere...
Feel free to experiment using this playground link to see for yourself. Remember to enable strictNullChecks!