typescript - 打字稿魔法属性
问题描述
我开始使用 Typescript 并且有点卡住了。是否可以允许 TypeScript 类使用在运行时添加的属性?我正在使用这样的东西:
interface IObject {
[key: string]: any;
}
class A {
private extends: IObject = {};
constructor() {
return new Proxy(this, {
get: (target: any, name: string) => (name in this.extends) ? this.extends[name] : target[name],
})
}
public extend(key: any, argument: object): A {
this.extends = Object.assign(this.extends, {
[key]: argument
});
return this;
}
}
所以这个类就像我的应用程序中的可扩展上下文。我可以在运行时在此处添加任何属性,aInstance.extend('property', {a: 1})
并像这样使用它们aInstance.property
。在纯 JS 中,它将{a: 1}
按预期返回,但 TypeScript 在执行此操作时会引发错误(“A”类型上不存在 Property 'property'。)。那么有什么办法可以避免这种情况吗?我知道我可以使用// @ts-ignore
,但我不想使用它,因为维护代码会更加困难。
将不胜感激在这里的任何建议。谢谢 :)
解决方案
我认为不可能完全按照您的意愿去做并保持类型安全。一种选择是执行以下操作:
class A {
private extends: Record<string, any> = {};
constructor() {
return new Proxy(this, {
get: (target: any, name: string) => (name in this.extends) ? this.extends[name] : target[name],
})
}
public extend<T extends object>(obj: T): A & T {
this.extends = Object.assign(this.extends, obj);
// necessary evil, but safe because we know we are returning A & T due to the proxy
return this as any;
}
}
let aInstance = new A()
let extended = aInstance.extend({"test": "foo"})
console.log(extended.test)
基本上,extend 方法现在返回的类型是 A 和 T 的并集。缺点是只有 extend 函数的返回值将被键入为具有额外属性。
我会考虑为什么首先需要在运行时扩展类型?
如果您提前知道属性名称,那么只需将它们添加到类中。否则,听起来地图可能更适合这项工作。
推荐阅读
- google-home - 谷歌主页布局控制工作但没有语音命令
- javascript - 无法从 nodejs 连接到 SQL 数据库
- python - Python map() 函数 - ValueError:无法将字符串转换为浮点数
- javascript - 如何从数组中生成随机数量的项目
- python - Python递归将元组列表排序为树结构
- python-3.x - 找到的解决方案:执行代码时出现此错误 --> TypeError: not enough arguments for format string
- c# - Visual Studio 2015 输出异常
- c# - 用于带有 gridcell 的 vb.net 应用程序的 Selenium sendkeys
- laravel - Axios 在 Laravel 中重复前缀路由
- python - OpenCV-python 不导入