Is there a way for the generic of a type to modify the type itself?
Can it be done without creating two functions?
This is not about js functionality, only about getting the types to match.
When I call a function with the generic HTMLInputElement
, I would like the return type to be Array<HTMLInputElement>
.
When I call it with HTMLSelectElement
it should be Array<HTMLSelectElement>
.
But, when I call it with never
or don't supply a generic, it should be string
.
Minified example, that doesn't work since the return type is always Array<T> | string
(T has the right value though):
type InteractiveElement = HTMLInputElement | HTMLSelectElement;
function getValue<T extends InteractiveElement = never>(): Array<T> | string {
return null as unknown as Array<T> | string; //
}
const inputValue = getValue<HTMLInputElement>(); // should be ChangeEvent<HTMLInputElement>
const selectValue = getValue<HTMLSelectElement>(); // should be ChangeEvent<HTMLSelectElement>
const emptyValue = getValue(); // should be string
You can do this either by overloading getValue()
so the non-generic call signature is first:
function getValue(): string;
function getValue<T extends InteractiveElement>(): Array<T>;
function getValue() {
return null!
}
const inputValue = getValue<HTMLInputElement>(); // Array<HTMLInputElement>
const selectValue = getValue<HTMLSelectElement>(); // Array<HTMLSelectElement>
const emptyValue = getValue(); // string
Or you can make the function return a conditional type which checks if T
is never
(which requires that the conditional type not be distributive, hence the wrapping with [
+]
) and returns string
if so, or Array<T>
if not:
function getValue<T extends InteractiveElement = never>():
[T] extends [never] ? string : Array<T> {
return null!
}
const inputValue = getValue<HTMLInputElement>(); // Array<HTMLInputElement>
const selectValue = getValue<HTMLSelectElement>(); // Array<HTMLSelectElement>
const emptyValue = getValue(); // string
Either way, this example cannot be properly implemented since there are no actual function parameters for the JavaScript to act upon. But since you said it was "minified" maybe it doesn't matter.