I'm writing some frontend code in TypeScript, creating some Custom Elements by hand.
Custom Elements let me define "observed attributes" as an array of strings. I want all of these observed attributes to also be properties on the class, so that I can for example myElement.attr1 = 'value'
instead of myElement.setAttribute('attr1', 'value')
. Right now, I'm achieving that with this metaprogrammy code:
class MyElement extends HTMLElement {
static get observedAttributes() {
return ['attr1', 'attr2', 'attr3'];
}
}
for (const attr of MyElement.observedAttributes) {
Object.defineProperty(MyElement.prototype, attr, {
get: function() { return this.getAttribute(attr) },
set: function(value) {
if (value === null) this.removeAttribute(attr);
else this.setAttribute(attr, value);
}
});
}
This works great, but TypeScript does not know about the properties I'm adding, even though they're all completely static. Is there some trick I can use to tell typescript that I'm adding properties for each string in observedAttributes
?
I've tried something like this:
const myObservedAttributes = {
'attr1': true,
'attr2': true,
'attr3': true,
};
type DynamicAttrs = {
[Key in keyof typeof myObservedAttributes]: string | null;
}
class MyElement extends HTMLElement implements DynamicAttrs {
static get observedAttributes() {
return Object.keys(myObservedAttributes);
}
}
// ... Object.defineProperty loop from above
but of course TypeScript complains that I'm not implementing any of the properties in DynamicAttrs
because it doesn't understand Object.defineProperty
.