我有一个JavaScript对象,它动态地允许成员作为对象实例的访问者属性绑定:
来源
function DynamicObject(obj) {
for (var prop in obj) {
Object.defineProperty(this, prop, {
get: function () { return obj[prop]; },
set: function (value) { obj[prop] = value; },
enumerable: true,
configurable: false
});
}
}
用法
var obj = new DynamicObject({
name: "John Smith",
email: "john.smith@test.net",
id: 1
});
创建obj
时,构造函数参数的成员将作为访问者属性绑定到obj
。这些出现在intellisense中
我想知道是否可以在TypeScript中模拟这种行为(包括智能感知)?
备注
当你在TypeScript中运行这段代码时,没有智能感知,因为一切都是any
,所以TypeScript并不真正知道发生了什么。
答案 0 :(得分:5)
你不能。这些是完全动态的属性,在运行时添加,因此您无法在编译时知道它们是什么。我还会争辩说,你不希望早点知道它们是什么;如果你有强制执行的限制,他们应该自己说明(下面的第一个例子)。
如果您的代码依赖于一组访问者,您应该将它们直接放在界面或合同中,因为您提前了解,并且应该宣传它们。您可以使用可选属性(将访问器定义为更低)来简化:
interface HasSomeProps {
foo: string;
bar?: string;
}
class DoesTheProps implements HasSomeProps {
set foo(value) {
// ...
}
}
如果你有一堆一致(或半一致)的访问者,你可以在你的类型上定义一个索引器,如:
interface AccessStrings {
[key: string]: string;
}
这不允许您限制密钥。如果需要,您应该明确列出属性。
答案 1 :(得分:2)
我想知道是否可以在TypeScript中模拟这种行为(包括智能感知)?
是强>
您可以为DynamicObject
分配通用呼叫签名。您需要将其声明为变量:
var DynamicObject: new <T>(obj: T) => T = function (obj)
{
for (var prop in obj)
{
Object.defineProperty(this, prop, {
get: function () { return obj[prop]; },
set: function (value) { obj[prop] = value; },
enumerable: true,
configurable: false
});
}
} as any;
这样,IntelliSense会将从new DynamicObject
返回的值视为与传入的值具有相同的类型。相同的属性名称,相同的属性类型。您将获得完全自动完成和类型安全。
Live demo on TypeScript Playground
如果您在第一行中绕着该部分缠绕时遇到困难,则与编写以下内容相同:
// Declare type (only exists during compile-time)
var DynamicObject: new <T>(obj: T) => T;
// Assign value (during runtime)
DynamicObject = function (obj)
{
...
} as any;