Is it possible to create a function where the return type is determined by a string, with some additional complexities involved? I'm looking to achieve the following:
- The parameter is contained within an object
- The parameter is optional
- The object itself is also optional
I want to know if this can be achieved. Here's a simplified version of what I have in mind:
interface NumberWrapper {
type: "my_number";
value: number;
}
const x1: number = fn(1, { returnType: "bare" });
const x2: NumberWrapper = fn(1, { returnType: "wrapped" });
const x3: void = fn(1, { returnType: "none" });
const x4: number = fn(1, {});
const x5: number = fn(1);
In the examples above, different ways are shown on how I intend to call my function fn()
and have TypeScript correctly deduce the return type.
For x1
, x2
, x3
, the function is called with a specified value for returnType
.
For x4
, no value is provided for returnType
, and I aim for it to default to "bare"
. Similarly, for x5
, when no object is supplied at all, it should act as if returnType
is "bare"
.
(You might be questioning why I'm placing returnType
in an object when it's just one parameter. In my real-world scenario, there are other parameters in the object.)
So far, I've managed to make x1
, x2
, and x3
work, but not x4
or x5
. This is what I currently have:
type ReturnMap<T extends "bare" | "wrapped" | "none"> = T extends "bare"
? number
: T extends "wrapped"
? NumberWrapper
: void;
function fn<T extends "bare" | "wrapped" | "none">(
x: number,
{ returnType }: { returnType: T }
): ReturnMap<T> {
if (returnType === "bare") {
return x as ReturnMap<T>;
} else if (returnType === "wrapped") {
return { type: "my_number", value: x } as ReturnMap<T>;
} else {
return undefined as ReturnMap<T>;
}
}
An issue I am facing is that each return
statement ends with return x as ReturnMap<T>
. I would prefer to avoid this as the as
may compromise some type safety.
However, the main challenge lies in making this work for x4
and x5
. I have attempted various approaches using default values, but have not succeeded so far.