Closed
Description
Search Terms
conditional return type narrowing generics
Suggestion
It seems like it should be possible to constrain the return type of a function using a conditional expression:
For example,
// I want my function to have a different return type depending on input
export function foo<T extends string|number>(
val: T // input type is a union
): T extends string ? string : number { // output type is either string or number
return val;
}
// expected this to work, but received:
// Type 'T' is not assignable to type 'T extends string ? string : number'.
// Type 'string | number' is not assignable to type 'T extends string ? string : number'.
// Type 'string' is not assignable to type 'T extends string ? string : number'.
Use Cases
A common use case is a function which can process single objects or arrays of objects, and returns single objects or an array, respectively.
Examples
// capitalize a string or each element of an array of strings
function capitalize<T extends string | string[]>(
input: T
): T extends string[] ? string[] : string {
if (isString(input)) {
return input[0].toUpperCase() + input.slice(1);
} else {
return input.map(elt => capitalize(elt));
}
}
Checklist
My suggestion meets these guidelines:
- This wouldn't be a breaking change in existing TypeScript / JavaScript code
- This wouldn't change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn't a runtime feature (e.g. new expression-level syntax)