Typescript return type depending on parameter
Both approaches are valid. If your function uses conditional types in the return it will need to use type assertions, as typescript will not try to reason about the conditional type since it contains a free type parameter:
function dependsOnParameter<B extends boolean>(x: B): B extends true ? number : string {
if (x) {
return 3 as any;
} else {
return "string"as any;
}
}
This approach uses any
which you want to avoid.
The second approach we can get to work without resorting to type assertions by just duplicating the last signature:
function dependsOnParameter(x: true): number;
function dependsOnParameter(x: false): string;
function dependsOnParameter(x: boolean): number | string
function dependsOnParameter(x: boolean): number | string {
if (x) {
return 3;
} else {
return "string";
}
}
function calling(x: boolean) {
dependsOnParameter(x); // returns number| string
dependsOnParameter(true); // returns number
dependsOnParameter(false); // returns string
}
The last signature is the implementation signature and is not publicly accessible. You can make it accessible by duplicating it. The compiler is not smart enough to combine the two overloads with true
/false
and decide the return type is string|number
Edit
We can also combine the two approaches for fewer signatures:
function dependsOnParameter<B extends boolean>(x: B): B extends true ? number : string
function dependsOnParameter(x: boolean): number | string{
if (x) {
return 3;
} else {
return "string";
}
}
This is one way:
function dependsOnParameter<B extends boolean>(x: B): B extends true ? number : string {
return (x === true ? 3 : "string") as B extends true ? number : string;
}
Here, the condition itself (B extends true ? number : string) is considered as a type. This type is called a Conditional Type.