Currently, I am in the process of developing a function called clone(el)
. This function needs to accept an HTMLElement
or any subtype of it and return the same type that is provided.
Can someone assist me in correctly structuring the generic signature for this function? Your help is greatly appreciated!
I suspect that my issue lies with point number two, specifically in how T
is being limited to HTMLElement
.
For context, I am coding in vanilla JavaScript and utilizing JSDoc within VS Code. Thankfully, there is a @template
definition available to establish generics:
- Define a generic
T
- Constrain
T
to be of typeHTMLElement
or its subtypes - Set both the first parameter and return type as the generic
T
- Utilize
, which returns andocument.createElement(tagName: string)
HTMLElement
- Ensure that the return type of
createElement
matches with typeT
– while I know they will align since creating an element with the same tagName always results in the same type of element, the method itself does not possess this knowledge due to the lack of specific information regardingel.tagName
, only recognizing it as a type ofstring
.
/**
* @template {HTMLElement} T
* @param {T} el
* @returns {T}
*/
function clone(el) {
/** @type {T} */
const newEl = document.createElement(el.tagName);
// ^^^^^ Error from above appears on this
// perform attribute and child node copying here
return newEl;
}
I anticipate the TypeScript equivalent to yield a similar outcome:
function clone<T extends HTMLElement>(el: T): T {
const newEl: T = document.createElement(el.tagName);
// conduct attribute and child node copying here
return newEl;
}
However, TypeScript raises an error message stating:
Type 'HTMLElement' is not assignable to type 'T'.
'HTMLElement' fits within the constraint of type 'T', but 'T' might also embody another subtype under 'HTMLElement'. (2322)
The error seems logical to me, especially when I try to simplify the problem by providing a specific example, resulting in a clearer understanding of the issue:
function clone<T extends HTMLElement>(el: T): T {
return document.createElement('input');
}
Type 'HTMLInputElement' cannot be assigned to type 'T'.
'HTMLInputElement' can conform to the limitations of type 'T', yet 'T' could potentially represent an alternate subtype falling under 'HTMLElement'. (2322)
While I attempted to seek guidance from , I sense that my situation introduces additional constraints as document.createElement
defines its type signature as
Document.createElement(tagName: string, options?: ElementCreationOptions | undefined): HTMLElement
.