0

I'm trying to understand how function overloading in typescript works.

type CreateElement = {
  (tag: 'a'): HTMLAnchorElement
  (tag: 'canvas'): HTMLCanvasElement
  (tag: 'table'): HTMLTableElement
}

let createElement: CreateElement = (tag: 'a' | 'canvas' | 'table') => {
  if (tag === 'a') return new HTMLAnchorElement()
  if (tag === 'canvas') return new HTMLCanvasElement()
  if (tag === 'table') return new HTMLTableElement()
  throw new Error('wrong tag');
}

The code above throws the error:

Type 'HTMLAnchorElement | HTMLCanvasElement | HTMLTableElement' is not assignable to type 'HTMLAnchorElement'.
    Type 'HTMLCanvasElement' is missing the following properties from type 'HTMLAnchorElement': charset, coords, download, hreflang, and 21 more.

I have ensured that I resolve the parameter tag before returning the appropriate type for a given tag type. Any ideas why this doesn't work?

2
  • Wouldn't CreateElement be type CreateElement = HTMLAnchorElement | HTMLCanvasElement | HTMLTableElement? Commented Jan 27, 2020 at 22:40
  • Not sure what you mean, I'm overloading the function by taking union of function signature but you're referring to union of objects. Commented Jan 27, 2020 at 22:45

1 Answer 1

1

Function overloads can only be used with function declarations.

Workarounds with "overloaded" (arrow) function expressions may work in a limited, weak typed way. But unlike the former, the compiler does not have a special treatment for these expressions. So they will not behave in the manner you expect it (your code error is already a good example).

Your rewritten example with proper function overloads looks like this:

function createElement(tag: 'a'): HTMLAnchorElement // overload 1
function createElement(tag: 'canvas'): HTMLCanvasElement // 2
function createElement(tag: 'table'): HTMLTableElement // 3 
function createElement(tag: 'a' | 'canvas' | 'table') { // fn implementation
    if (tag === 'a') return new HTMLAnchorElement()
    if (tag === 'canvas') return new HTMLCanvasElement()
    if (tag === 'table') return new HTMLTableElement()
    throw new Error('wrong tag');
}

const ret = createElement("a") // HTMLAnchorElement
Sign up to request clarification or add additional context in comments.

2 Comments

I see...this works. Only drawback is the need to repeat the function name compared to function expression.
yeah, I also like the leaner arrow function syntax a bit more (and you can declare function interface types for them). But this one will provide stronger types for the function implementation. So I would prefer it anytime.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.