Typescript使用`#private;`字段生成声明d.ts文件。

时间:2020-11-06 00:52:39

标签: javascript typescript typescript-typings

我有一个用Typescript编写的库,该库以2个文件分发:一个已编译的ECMAScript-2015兼容Javascript文件index.js和一个Typescript声明文件index.d.ts。我的目标是使Java开发人员和Typescript开发人员都可以访问库(以便他们进行正确的键入和自动填充)。

最近我已升级到Typescript 3.9.7,并决定将代码重构为使用新的私有类字段声明,该声明使用#标记而不是Typescript的private关键字。

令我惊讶的是,由于在我的课程中加入了index.d.ts成员,因此我的#private;文件与旧的Typescript版本不兼容。

这是在旧的Typescript代码生成旧的声明文件与新的重构的Typescript代码生成新的不兼容的声明文件之间进行比较。使用private关键字的旧代码:

// index.ts
class MyClass {
    private field1: string = "foo";
    private field2: string = "bar";

    constructor() {
        console.log(this.field1, this.field2);
    }
}

// generated index.d.ts
declare class MyClass {
    private field1;
    private field2;
    constructor();
}

使用#标记来声明私有名称的新的重构代码:

// index.ts
class MyClass {
    #field1: string = "foo";
    #field2: string = "bar";

    constructor() {
        console.log(this.#field1, this.#field2);
    }
}

// generated index.d.ts
declare class MyClass {
    #private;
    constructor();
}

这里是a page at Typescript playground,其中包含该示例代码。

现在,如果我的客户使用旧的Typescript(例如3.7版)将获取我的库(由已编译的index.js和声明文件index.d.ts组成,而没有源index.ts文件)并依靠index.d.ts类型,他们会看到以下错误:

error TS1127: Invalid character.

该错误的根源很清楚(#标记),所以我的问题如下:

  1. 如果我在将库运送给客户之前无需处理实现细节,就可以对index.d.ts进行后处理并删除#private;行,可以吗?我可以使用ttsc包轻松地做到这一点,但我仍然担心键入信息可能会以某种方式很重要。
  2. #private;index.d.ts行的实际用途是什么?为什么声明文件为什么会公开类利用私有字段(如果无论如何都不能访问它们)以及实现细节?
  3. 根据a topic in Typescript Github issues,这是预期的行为,因此带有私有字段的类在被发送到.d.ts文件时将保留其名义上的键入行为。可悲的是,那个解释的意思从我身边溜走了。我是否可以阅读其他文档以更好地了解Typescript的名义打字行为?

3 个答案:

答案 0 :(得分:5)

它使类型成为“标称”类型,以便暴露相同公共成员的其他类型不被视为与具有私有字段的类型兼容。一种重要的情况是您是否具有以下代码:

class C {
    #foo = "hello";
    bar = 123;

    static log(instance: C) {
        console.log("foo = ", instance.#foo, " bar = ", instance.bar);
    }
}

我敢肯定还有更多的例子,但是这种静态方法只是我脑海中浮现的一种方法。

C.log函数需要一个C类的实际实例,因为它访问instance参数上的私有实例字段。如果声明发出表明C类型是名义上的,则表明它具有ES私有字段,而仅发出公共字段,那么编译器将在此处使用结构类型比较,并且不会产生预期的结果输入错误。例如,该声明发出将允许相关代码在没有任何编译器错误的情况下将{ bar: 456 }传递到C.log

答案 1 :(得分:1)

我试图回答您的问题,但未能回答,然后出于好奇,我问了我自己的问题,这是由TypeScript贡献者回答的,您可以在这里找到他的答案:What's the purpose of #private in TypeScript definition files?

总而言之,在某些情况下,当涉及到类型之间的比较时,私有字段很重要,这就是为什么出现#private字段,以便信息“包含私有成员”成为类型定义的一部分的原因。

答案 2 :(得分:-3)

#private语法当前是JavaScript的stage-3 proposal。一旦浏览器支持它,它将不会被打字稿编译。