簡體   English   中英

Typescript 生成帶有 `#private;` 字段的聲明 d.ts 文件

[英]Typescript generates declaration d.ts file with `#private;` field

我有一個用 Typescript 編寫的庫,它分布在 2 個文件中:一個編譯的 ECMAScript-2015 兼容的 Javascript 文件index.js和一個 Typescript 聲明文件index.d.ts 我的目標是讓 Javascript 和 Typescript 開發人員都可以訪問庫(以便他們具有正確的類型和自動完成功能)。

最近我升級到 Typescript 3.9.7,並決定重構我的代碼以使用新的私有類字段聲明,該聲明使用# sigil 而不是 Typescript 的private關鍵字。

令我驚訝的是,由於包含#private; ,我的index.d.ts文件與舊的 Typescript 版本不兼容#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();
}

這是Typescript 游樂場的一個頁面,其中包含該示例代碼。

現在,如果我的客戶使用舊的 Typescript(比如 3.7 版)將獲取我的庫(由編譯的index.js和聲明文件index.d.ts ,沒有源index.ts文件)並依賴於index.ts index.d.ts類型,他們會看到以下錯誤:

error TS1127: Invalid character.

該錯誤的起源很清楚( # sigil),所以我的問題如下:

  1. 如果我后處理我的index.d.ts並刪除#private; 在我將我的庫發送給客戶之前,不必知道實現細節? 我可以通過使用ttsc包輕松做到這ttsc ,但我仍然擔心輸入信息可能在某種程度上很重要。
  2. #private;的實際用途是#private; index.d.ts行? 為什么聲明文件會公開一個類使用私有字段,如果它們無論如何都無法訪問,並且是實現細節?
  3. 根據Typescript Github 問題中的一個主題,這是預期的行為,以便具有私有字段的類在發送到.d.ts文件時保留其名義輸入行為。 可悲的是,那個解釋的意義從我身上溜走了。 是否有任何額外的文檔我可以閱讀以更好地理解 Typescript 的標稱打字行為?

它使類型成為“名義”類型,因此公開相同公共成員的其他類型不會被視為與具有私有字段的類型兼容。 這很重要的一種情況是,如果您有這樣的代碼:

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

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

我確信還有更多的例子,但這個靜態方法只是我想到的一個。

C.log函數需要C類的實際實例,因為它訪問instance參數上的私有命名實例字段。 如果聲明emit 沒有通過表明它具有ES 私有字段而反映C類型是名義型的,而是僅發出公共字段,則編譯器將在此處使用結構類型比較並且不會產生預期的類型錯誤。 例如,該聲明發出將允許依賴代碼將{ bar: 456 }傳遞到C.log而不會出現任何編譯器錯誤。

我試圖回答您的問題但無法回答,然后出於好奇,我提出了自己的問題,這是由 TypeScript 貢獻者回答的,您可以在這里找到他的答案: TypeScript 定義文件中 #private 的目的是什么?

總而言之,在某些情況下,當涉及到類型之間的比較時,私有字段很重要,這就是為什么會出現#private字段,以便信息“包含私有成員”成為類型定義的一部分。

#private 語法目前是 JavaScript的第 3 階段提案 一旦瀏覽器支持它,它就不會被打字稿轉譯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM