Javascript Typescript生成带有`#private;`的声明d.ts文件领域

Javascript Typescript生成带有`#private;`的声明d.ts文件领域,javascript,typescript,typescript-typings,Javascript,Typescript,Typescript Typings,我有一个用Typescript编写的库,它被分为两个文件:一个编译的ECMAScript-2015兼容Javascript文件index.js和一个Typescript声明文件index.d.ts。我的目标是让Javascript和Typescript开发人员都可以访问这个库(这样他们就有了正确的键入和自动完成) 最近我升级到了Typescript 3.9.7,并决定重构我的代码以使用新的私有类字段声明,该声明使用sigil而不是Typescript的private关键字 令我惊讶的是,我的in

我有一个用Typescript编写的库,它被分为两个文件:一个编译的ECMAScript-2015兼容Javascript文件
index.js
和一个Typescript声明文件
index.d.ts
。我的目标是让Javascript和Typescript开发人员都可以访问这个库(这样他们就有了正确的键入和自动完成)

最近我升级到了Typescript 3.9.7,并决定重构我的代码以使用新的私有类字段声明,该声明使用
sigil而不是Typescript的
private
关键字

令我惊讶的是,我的
index.d.ts
文件由于包含
#private我的类上的成员

下面是生成旧声明文件的旧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();
}
使用
#
sigil声明私有名称的新重构代码:

// 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();
}
下面是包含该示例代码的

现在,如果使用旧类型脚本(比如说3.7版)的客户将获取我的库(由编译的
index.js
和声明文件
index.d.ts
,没有源
index.ts
文件)并依赖
index.d.ts
类型,他们将看到以下错误:

error TS1127: Invalid character.
该错误的根源很清楚(即
#
信号),因此我的问题如下:

  • 如果我对我的
    index.d.ts进行后处理并删除
    #private,可以吗行在我将库交付给客户之前,您不必知道实现细节吗?通过使用
    ttsc
    package,我可以很容易地做到这一点,但我仍然担心键入的信息可能在某种程度上很重要
  • #private的实际用途是什么索引中的行.d.ts
    ?如果不能访问私有字段,为什么声明文件会公开类使用私有字段,以及实现细节
  • 根据,这是预期的行为,因此具有私有字段的类在发送到
    .d.ts
    文件时保留其标称键入行为。可悲的是,这个解释的意义从我身上消失了。为了更好地理解Typescript的标称键入行为,我是否可以阅读其他文档
  • #私有语法目前是javascript的一个重要特性。一旦浏览器支持它,它就不会被typescript传输。

    它使类型成为“标称”类型,因此暴露相同公共成员的其他类型不会被视为与具有私有字段的类型兼容。如果您有这样的代码,这一点很重要:

    class C {
        #foo = "hello";
        bar = 123;
    
        static log(instance: C) {
            console.log("foo = ", instance.#foo, " bar = ", instance.bar);
        }
    }
    
    我确信还有更多的例子,但这个静态方法只是我脑海中浮现的一个


    C.log
    函数需要
    C
    类的实际实例,因为它访问
    instance
    参数上的私有命名实例字段。如果声明emit没有通过指示
    C
    类型具有ES私有字段而反映出该类型是标称的,而是只发出公共字段,那么编译器将在此处使用结构类型比较,并且不会产生预期的类型错误。例如,该声明将允许依赖代码传入
    {bar:456}
    C.log
    ,而没有任何编译器错误。

    我试图回答您的问题,但无法回答,然后出于好奇我问了自己的问题,TypeScript贡献者回答了这个问题,您可以在这里找到他的答案:


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

    问题不在于私有字段是什么。这就是发出的定义中神秘的
    #private
    成员的含义。啊……所以听起来你的问题是“如何发出向后兼容的typescript定义文件”…我猜Typescript假设声明文件使用者会理解该语法。事实上,我尝试了另一个
    测试
    类,该类编译为与示例类相同的
    .d.ts
    ,而不是您的示例类(相同的公共成员,不同的私有成员),当我键入
    C.log(新测试)类型“Test”中的I get属性“#private”指的是无法从类型“C”中访问的其他成员。。谢谢你的解释。我让主持人把我的问题和这个(原来的)问题合并起来,这样你就有资格获得赏金了