JavaScript到TypeScript:Intellisense和动态成员

时间:2016-10-06 15:27:49

标签: javascript typescript

我有一个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中

Intellisense for dynamic members

我想知道是否可以在TypeScript中模拟这种行为(包括智能感知)?

备注

当你在TypeScript中运行这段代码时,没有智能感知,因为一切都是any,所以TypeScript并不真正知道发生了什么。

2 个答案:

答案 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;