Home > Software engineering >  From an arrow function with a string parameter, how can I return the correct type?
From an arrow function with a string parameter, how can I return the correct type?

Time:09-03

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]
}

Playground

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");
  • Related