3

According to TypeScript documentation (look for the String Literal Types section), the following code should work on TypeScript:

function createElement(tagName: "img"): HTMLImageElement;
function createElement(tagName: "input"): HTMLInputElement;
// ... more overloads ...

function createElement(tagName: string): Element {
    // ... code goes here ...
}

When I run the code, or some more meaningful variation, on TypeScript Playground, or on Visual Studio, I get the following error:

Specialized overload signature is not assignable to any non-specialized signature.

Any suggestion? I came to this error after trying to implement something very similar on my own code.

3 Answers 3

1

Did you try to start with a non specialized signature?

function createElement(tagName: string): Element;
function createElement(tagName: "img"): HTMLImageElement;
function createElement(tagName: "input"): HTMLInputElement;
// ... more overloads ...

function createElement(tagName: string): Element { /* ... */ }

```

Sign up to request clarification or add additional context in comments.

2 Comments

It works, thanks! Great! Do you have any explanation why does it work? I'm trying to understand.
Not sure, maybe because specialized signatures can't see the implementation that comes after them? More details here.
0

Answering to my own question: IMHO, the use of Generics can solve this kind of problems in a better way.

String Literals + Function Overloading approach

function createElement(tagName: string): Element;
function createElement(tagName: "img"): HTMLImageElement;
function createElement(tagName: "input"): HTMLInputElement;
// ... more overloads ...

function createElement(tagName: string): Element { /* ... */ }

var inputElement = createElement("input");

Generics approach

function createElement<elementType>(): elementType { /* ... */ }

var inputElement = createElement<HTMLInputElement>();

Generics approach with stronger type constraints

function createElement<elementType extends HTMLElement>(): elementType { /* ... */ }

var inputElement = createElement<HTMLInputElement>();

Comments

0

If you want to restrict to only the specified strings (e.g. when other cases are an error) you apparently have to alias the type first.

type ValidTagOptions = "img" | "input";
function createElement(tagName: ValidTagOptions): HTMLImageElement;
function createElement(tagName: ValidTagOptions): HTMLInputElement;

This is trigger a compiler error when calling:

createElement("a"); // Error!

You can't just start doing it with the literals in the function signature, as you found. Annoying, IMO. I hope they clean this up in future TS versions!

Comments

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.