如何在 TypeScript 类 中正确声明计算的 属性 名称?
How to properly declare computed property names in TypeScript classes?
简而言之
如何在 TypeScript 中声明:在这个 class 中,任何以 '$' 开头的 属性 都是对元素 的引用?
上下文
我有一个自定义元素 class 方法,它自动将任何具有属性 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 种解决方法,但其中 none 完全令人满意。
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
我更接近了,但它仍然不等同于香草 JavaScript 版本。
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 还很陌生。
提前致谢!
typescript 无法对您的 html 代码生成静态检查,它不能给定 html 是动态的(您可以使用 [=12 动态生成 DOM =] attributes) 2 或 3 都是可行的选项。想一想:打字稿在编译期间检查类型,在交付之前,HTML 可以稍后在运行时填充额外的元素。
如果你事先知道你的元素,你可以为打字稿提供静态类型信息。例如对于 (3) 选项:
class SomeComponent extends HTMLElement {
[x: '$myRef' | '$myOtherRef']: HTMLElement; // ok
....
或者你可以只用普通的 属性:
class SomeComponent extends HTMLElement {
$myProp: HTMLElement
....
简而言之
如何在 TypeScript 中声明:在这个 class 中,任何以 '$' 开头的 属性 都是对元素 的引用?
上下文
我有一个自定义元素 class 方法,它自动将任何具有属性 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 种解决方法,但其中 none 完全令人满意。
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
我更接近了,但它仍然不等同于香草 JavaScript 版本。
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 还很陌生。 提前致谢!
typescript 无法对您的 html 代码生成静态检查,它不能给定 html 是动态的(您可以使用 [=12 动态生成 DOM =] attributes) 2 或 3 都是可行的选项。想一想:打字稿在编译期间检查类型,在交付之前,HTML 可以稍后在运行时填充额外的元素。
如果你事先知道你的元素,你可以为打字稿提供静态类型信息。例如对于 (3) 选项:
class SomeComponent extends HTMLElement {
[x: '$myRef' | '$myOtherRef']: HTMLElement; // ok
....
或者你可以只用普通的 属性:
class SomeComponent extends HTMLElement {
$myProp: HTMLElement
....