I created a function for creating dynamic element. But instead of returning the literal type of the element it is returning the union of <HTMLElementTagNameMap>
.
function createElement(type: keyof HTMLElementTagNameMap) {
return document.createElement(type)
}
If we just use the above function it is returning the Union of :
(HTMLElement | HTMLObjectElement | HTMLAnchorElement | HTMLAreaElement | HTMLAudioElement | ... 57 more ... | HTMLVideoElement).
What I have tried so far :
type valueOf<T> = T[keyof T]
function createElement<T extends valueOf<HTMLElementTagNameMap>>(type: keyof HTMLElementTagNameMap) {
return document.createElement(type) as T
}
P.S - I am also quite confused! How'd the above function worked?
but instead using the above function in the way like mentioned below :
const div = createElement<HTMLDivElement>('div')
I want it to infer automatically the type of type
like it does when we use :
let li = document.createElement('li')
CodePudding user response:
The code works because you're passing the return type manually by the generic type T
.
you can automate that by the code below:
const createElement = <K extends keyof HTMLElementTagNameMap>(name: K): HTMLElementTagNameMap[K]{
return document.createElement(name)
}
const div = createElement('div')
console.log(div)
// [LOG]: HTMLDivElement: {}
it's not so different than the one you've written. I hope it helped. if you have any questions you are welcome to ask in comments
CodePudding user response:
If you want the same behaviour as document.createElement
you can write simply
function createElement<K extends keyof HTMLElementTagNameMap>(type: K) {
return document.createElement(type);
}
or if you want to pick tag name by HTML element, you can use something like this
type PickTagNameForHTMLElement<TargetElement> = {
[K in keyof HTMLElementTagNameMap]: HTMLElementTagNameMap[K] extends TargetElement ? K : never;
}[keyof HTMLElementTagNameMap];
function createElement<TargetElement extends HTMLElement>(type: PickTagNameForHTMLElement<TargetElement>) {
return document.createElement(type);
}