Typescript使用未分配的变量world
编译以下类:
class Hello {
world: string;
}
到以下javascript ,不带变量world
的声明:
var Hello = (function () {
function Hello() {
}
return Hello;
}());
但是,如果您将变量分配给任何:
class Hello {
world: string = undefined;
}
然后包含变量的声明:
var Hello = (function () {
function Hello() {
this.world = undefined;
}
return Hello;
}());
为什么在没有为world
分配默认值的情况下赢得了new Hello().hasOwnProperty('world')
的声明?
例如以下代码:
false
第一种情况返回true
,第二种情况返回{{1}}。我确实希望它是真的,因为我已经在Typescript中声明了它(虽然我没有给它赋值)。
我也无法为此找到编译器选项。我错过了什么吗?为什么Typescript会这样做?
答案 0 :(得分:3)
打字稿只是添加"语法糖"在javascript之上,但最后它被编译为js并且取决于js中支持的内容。
如果您查看es6 classes,您会发现没有相应的方式来声明成员在打字稿中完成的方式,成员定义只发生在构造函数中。< / p>
因此,除非您为其分配值,否则无法添加成员 只有两个选择:
将方法添加到原型中,但仅将成员添加到构造函数中发生的实例。
有几种方法可以解决这个问题,最直接的方法是手动将undefined
分配给构造函数中的所有成员(如您所述),但这并不能很好地扩展..
你可以&#34;自动化&#34;它有几种方式,其中一种方法是使用decorators。在您的情况下,虽然您需要使用两个装饰器,一个用于the class,另一个用于the members。
这里似乎有用的东西:
type RegistryEntry = {
property: string;
defaultValue: any;
}
const Registry = new Map<string, RegistryEntry[]>();
function AssignDefaultValues(target: any) {
var original = target;
function construct(constructor, args) {
var c: any = function () {
return constructor.apply(this, args);;
}
c.prototype = constructor.prototype;
const instance = new c();
const entries = Registry.get(original.name) || [];
entries.forEach(entry => {
instance[entry.property] = entry.defaultValue;
});
return instance;
}
var f: any = function (...args) {
return construct(original, args);
}
f.prototype = original.prototype;
return f;
}
function DeclareProperty(defaultValue: any = undefined) {
return function (target: any, property: string) {
const className = target.constructor.name;
let entries: RegistryEntry[];
if (Registry.has(className)) {
entries = Registry.get(className);
} else {
entries = [];
Registry.set(className, entries);
}
entries.push({
property,
defaultValue
});
}
}
@AssignDefaultValues
class Hello {
@DeclareProperty()
world: string;
}
let hello = new Hello();
console.log(hello.hasOwnProperty("world")); // true
这是一个很长的解决方案,但它似乎正在完成这项工作。