Вкратце
Как я могу объявить в TypeScript: В этом классе любое свойство, начинающееся с '$', является ссылкой на элемент ?
Контекст
У меня есть метод класса Custom Element, который автоматически сохраняет любой дочерний элемент с атрибутом data-reference
в свойстве, названном по его значению с префиксом «$». Прекрасно работает в ванили JavaScript:
class SomeComponent extends HTMLElement {
connectedCallback() {
this.setReferences()
console.log(this.$myRef) // <div data-reference="myRef"></div>
}
setReferences() {
const referencedElements = this.querySelectorAll('[data-reference]')
referencedElements.forEach((element) => {
const referenceName = '$' + element.getAttribute('data-reference')
this[referenceName] = element
})
}
}
customElements.define('some-component', SomeComponent)
<some-component>
<div data-reference="myRef"></div>
</some-component>
Но это не будет компилироваться в TypeScript, кто не знает о свойстве $myRef
:
console.log(this.$myRef) // Property '$myRef' does not exist on type 'SomeComponent'
^^^^^^
Пока что я Я придумал 3 обходных пути, но ни один из них не удовлетворяет полностью.
1. Утверждение типа
Нет!
console.log((this as any).$myRef) // <div data-reference="myRef"></div>
Смысл в том, чтобы обеспечить быстрый доступ к любому $ref
, поэтому добавление as any
или <any>
(плюс круглые скобки) нецелесообразно раствор.
2. Литеральный объект
Вероятно, самый чистый, но не совсем то, чего я хочу достичь.
type ElementReferenceMap = { [key: string]: Element }
class SomeComponent extends HTMLElement {
ref: ElementReferenceMap = {};
setReferences() {
const referencedElements = this.querySelectorAll('[data-reference]');
referencedElements.forEach((element) => {
const referenceName = element.getAttribute('data-reference');
this.ref[referenceName] = element as Element;
})
console.log(this.ref.myRef); // <div data-reference="myRef"></div>
}
}
Переименовав его в this.$.myRef
Я подхожу ближе, но он все еще не эквивалент ванили * Версия 1048 *.
3. Свойство индекса
Работает, как ожидалось (как версия JavaScript), но кажется неправильным, поскольку допускает любое значение свойства.
class SomeComponent extends HTMLElement {
// [x: string]: Element; // conflict with other properties
[x: string]: any; // ok
setReferences() {
const referencedElements = this.querySelectorAll('[data-reference]');
referencedElements.forEach((element) => {
const referenceName = '$' + element.getAttribute('data-reference');
this[referenceName] = element;
})
console.log(this.$myRef); // <div data-reference="myRef"></div>
}
}
Я могу упустить очевидное решение, так как я новичок в TypeScript. Заранее спасибо!