Optional, Rest Parameters, and Overloads

Use overload signatures when a function supports multiple call shapes and callers should receive a different precise return type based on the arguments. The overload signatures are visible to callers; the implementation signature is used to implement the behavior and must accommodate all overloads.

Do not add overloads merely to avoid a union type. If the input and output relationships are simple, a union or generic function may be clearer. Runtime checks must still implement each promised case; overload declarations do not generate runtime behavior.

Overloaded function
function parseValue(value: string): string[];
function parseValue(value: number): number;
function parseValue(value: string | number): string[] | number {
  if (typeof value === "string") return value.split(",");
  return value * 2;
}

const parts = parseValue("a,b"); // string[]
const doubled = parseValue(4);   // number
💡 The public overloads provide precise results for each input type. The implementation accepts the union and narrows it with typeof.
Key Takeaways
  • Overloads describe supported call signatures.
  • The implementation must handle every declared case.
  • Use overloads when they improve call-site precision.
Knowledge Check

Do overload signatures themselves create separate runtime implementations?