Yes, you can use overload signatures to achieve exactly what you want:
type Fruit = "apple" | "orange" function doSomething(foo: "apple"): string; function doSomething(foo: "orange"): string[]; function doSomething(foo: Fruit): string | string[] { if (foo == "apple") return "hello"; else return ["hello", "world"]; } let test1: string[] = doSomething("orange"); let test2: string = doSomething("apple");
Live demo on TypeScript Playground
Attempting to assign doSomething("apple") test1 will result in a compile-time type error:
let test1: string[] = doSomething("apple"); // ^^^^^ // type string is not assignable to type string[]
It is important to note that the definition of the overload signature used must always be done manually when implementing the function, and the implementation of the function must support all overload signatures .
TypeScript does not have separate implementations for each overload, as, for example, in C #. Therefore, I find it appropriate to strengthen TypeScript type checks at runtime, for example:
switch (foo) { case "apple": return "hello"; case "orange": return ["hello", "world"]; default: throw new TypeError("Invalid string value."); }
John weisz
source share