typescript - 为什么 Typescript 不声明未赋值的变量?

标签 typescript

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;
}());

当没有分配默认值时,为什么 Typescript 不添加 world 的声明?

例如下面的代码:

new Hello().hasOwnProperty('world')

对于第一种情况返回 false,对于第二种情况返回 true。我实际上确实希望它是真的,因为我已经在 Typescript 中声明了它(尽管我没有为其分配值)。

我也找不到为此的编译器选项。我错过了什么吗? Typescript 为什么要这样做?

最佳答案

Typescript 只是在 javascript 之上添加了“语法糖”,但最终它被编译为 js,并且取决于 js 所支持的内容。

如果你看es6 classes您会发现,没有与 typescript 中声明成员的方式等效的方法,成员定义仅发生在构造函数内部。

因此,除非您为成员分配值,否则无法添加成员。
只有两个选择:

  1. 添加到原型(prototype)
  2. 添加到实例

方法被添加到原型(prototype)中,但成员仅添加到构造函数中发生的实例中。


编辑

有几种方法可以解决这个问题,最简单的一种是手动将 undefined 分配给构造函数中的所有成员(正如您已经提到的),但这无法扩展嗯..

您可以通过多种方式“自动化”它,其中之一是使用 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

( code in playground )

这是一个很长的解决方案,但它似乎正在完成工作。

关于typescript - 为什么 Typescript 不声明未赋值的变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42899838/

相关文章:

javascript - InnerHTML在使用viewContainerRef.createComponent()再添加数据时没有属性数据

javascript - Typescript 可为 null 的回调

javascript - 通过 .catch() 传播被拒绝的 promise

c# - 如何使用 signalr 将 json 对象发送到 .net 服务器

typescript - 如何安装与旧版 TypeScript 兼容的@types?

javascript - 您将如何为 x-tag 组件定义 Typescript 接口(interface)签名

javascript - 无需在调用类中订阅即可获取可观察的返回值

node.js - TSC 找不到全局对象的名称

javascript - Jest 模拟 documentElement lang 属性

typescript - 如何在 Typescript 接口(interface)中为函数定义返回类型 void?