tezvyn:

How do you type a function with string and number overloads?

AI-drafted, machine-checkedSource: typescriptlang.orgintermediate

Tests if you know overloads are public API and the implementation uses a union. Answer: write process(string):string and process(number):number overloads, then implement with string|number and narrow. Red flag: exposing only the implementation signature.

WHAT THIS TESTS: This question probes whether you understand that TypeScript function overloads are a compile-time feature for describing multiple call signatures, not runtime branching. The interviewer wants to see that you know overload signatures sit above the single implementation signature, that the implementation signature must be wide enough to cover every overload, and that the implementation signature is hidden from consumers. It also checks if you know that overload resolution is ordered, meaning TypeScript tries each overload from top to bottom and uses the first match.

A GOOD ANSWER COVERS: First, write the two overload signatures in order: function process(x: string): string; and function process(x: number): number;. Second, provide the implementation signature immediately after them: function process(x: string | number): string | number. Third, explain that the implementation body must narrow the type, for example using typeof x === "string" to return a string and otherwise return a number. Fourth, note that callers only see the overload signatures, so process("foo") is typed as string and process(42) is typed as number, while process(Math.random() > 0.5 ? "foo" : 42) resolves via the last overload or may error if no matching overload exists. You should also mention that the implementation signature cannot be called directly by external code, so the overloads are the only contract consumers can rely on.

COMMON WRONG ANSWERS: Writing only the implementation signature and expecting TypeScript to infer the conditional return type. Using any for the implementation parameter or return type, which defeats type safety. Putting the implementation signature above the overloads, which is a syntax error. Writing the implementation signature as function process(x: string): string without the union, which fails to cover the number overload. Suggesting a generic with a type parameter constrained to string or number, which works in simple cases but is not function overloading and may not satisfy the interviewer if they specifically asked for overloads. Another mistake is returning a union from the overloads themselves, like function process(x: string | number): string | number, which erases the specific mapping and makes the overloads useless.

LIKELY FOLLOW-UPS: How does overload resolution work when multiple overloads could match? What happens if you add a boolean overload and forget to update the implementation signature? Why not use a conditional type or generic instead of overloads? When are overloads preferable to union types in the parameter list?

ONE CONCRETE EXAMPLE: function process(x: string): string; function process(x: number): number; function process(x: string | number): string | number { if (typeof x === "string") { return x.toUpperCase(); } return x multiplied by 2; } Here the first two lines are the callable interface; the third line is the hidden implementation that TypeScript checks against both overloads.

Read the original → typescriptlang.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.