如何在 TypeScript 类中正确声明计算属性名称?
Posted
技术标签:
【中文标题】如何在 TypeScript 类中正确声明计算属性名称?【英文标题】:How to properly declare computed property names in TypeScript classes? 【发布时间】:2020-10-07 02:49:16 【问题描述】:总之
如何在 TypeScript 中声明:在这个类中,任何以“$”开头的属性都是对元素的引用?
上下文
我有一个自定义元素类方法,它自动将任何具有data-reference
属性的子元素存储在一个属性中,该属性以它的值命名,前缀为'$'。
它在 vanilla 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
我更接近了,但它仍然不等同于原生 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 很陌生。 提前致谢!
【问题讨论】:
第二个选项是要走的路。 “任何以 '$' 开头的属性”的问题 - 无法真正验证 【参考方案1】:typescript 无法对您的 html 代码生成静态检查,它只是不能让 html 成为动态的(您可以使用data-reference
属性动态生成 DOM)2 或 3 都是可行的选择。想一想:typescript 在编译时检查类型,在交付之前,HTML 可以在以后填充额外的元素,在运行时。
如果你事先知道你的元素,你可以为打字稿提供静态类型信息。例如对于 (3) 选项:
class SomeComponent extends HTMLElement
[x: '$myRef' | '$myOtherRef']: HTMLElement; // ok
....
或者你可以只拥有一个普通的属性:
class SomeComponent extends HTMLElement
$myProp: HTMLElement
....
【讨论】:
好吧,我没想到打字稿会直接在 HTML 上检查,我想知道是否有类似于您的第一个示例的解决方案,例如[x: '$' + string]: HTMLElement
(当然这没有任何意义,但您明白了)。此外,这个想法是任何class SomeDerivingComponent extends SomeComponent
都会自动获得自己的参考,所以如果我必须明确它们,我有点错过了这一点。但我知道我正在寻找的东西不存在。感谢您的回答!
我不知道这个建议有多好(意思是请持保留态度),但在这种情况下我通常最终会做的是手动生成打字稿定义。就像编写一个小的 Python 脚本,它可能会解析您的 html(或其他东西,idk?)并生成 .ts
文件,其中包含您需要的类型定义。这实际上比听起来容易得多,但这是增加的支持。以上是关于如何在 TypeScript 类中正确声明计算属性名称?的主要内容,如果未能解决你的问题,请参考以下文章