Lets say I have an HTML file.
...
<div id="my-div"></div>
<span id="my-span"></span>
<input id="my-input">
...
I want to create an exported function so I can use this as so:
export const getKnownElement = (id: "my-div" | "my-span" | "my-input"): HTMLDivElement | HTMLSpanElement | HTMLInputElement => {
switch(id){
case "my-div":
return document.getElementById(id) as HTMLDivElement;
case "my-span":
return document.getElementById(id) as HTMLSpanElement;
case "my-input"
return document.getElementById(id) as HTMLInputElement;
}
}
When I use this function elsewhere. I'd like to know the outcome without any additional effort.
// myDiv knows it is a HTMLDivElement
const myDiv = getKnownElement("my-div")
How can I achieve this?
I know about function overloading but that isn't quite what I want although I have tried to simplify the question here.
CodePudding user response:
I would make getKnownElement
generic and use a simple type map for the return type.
type ElementMap = {
"my-div": HTMLDivElement
"my-span": HTMLSpanElement
"my-input": HTMLInputElement
}
const getKnownElement = <K extends keyof ElementMap>(id: K): ElementMap[K] => {
return document.getElementById(id) as ElementMap[K]
}
CodePudding user response:
You need to use function overloading, which unfortunately can't be used with the const __ = () => __;
syntax.
This also leads to some duplicate code in the method headers, but that's a small price to pay.
function getKnownElement(id: "my-div"): HTMLDivElement;
function getKnownElement(id: "my-span"): HTMLSpanElement;
function getKnownElement(id: "my-input"): HTMLInputElement;
function getKnownElement(id: "my-div" | "my-span" | "my-input"): HTMLDivElement | HTMLSpanElement | HTMLInputElement {
switch(id){
case "my-div":
return document.getElementById(id) as HTMLDivElement;
case "my-span":
return document.getElementById(id) as HTMLSpanElement;
case "my-input":
return document.getElementById(id) as HTMLInputElement;
}
}
const foo = getKnownElement("my-div");
const bar = getKnownElement("my-span");
const baz = getKnownElement("my-input");