簡體   English   中英

在 TypeScript 中使用導入類型的環境聲明

[英]Ambient declaration with an imported type in TypeScript

我的 TypeScript 項目中有一個聲明文件,如下所示:

// myapp.d.ts
declare namespace MyApp {
  interface MyThing {
    prop1: string
    prop2: number
  }
}

這很好用,我可以在我的項目中的任何地方使用這個命名空間,而無需導入它。

我現在需要從 3rd 方模塊導入一個類型並在我的環境聲明中使用它:

// myapp.d.ts
import {SomeType} from 'module'

declare namespace MyApp {
  interface MyThing {
    prop1: string
    prop2: number
    prop3: SomeType
  }
}

編譯器現在抱怨它找不到命名空間“MyApp”,大概是因為導入阻止它成為環境。

是否有一些簡單的方法可以在使用 3rd-party 類型的同時保留聲明的環境性?

是的,有辦法。 在 TypeScript 2.9 中使用import() 類型變得更容易,但在早期版本的 TypeScript 中也可以。

以下文件是一個腳本 腳本中聲明的東西被添加到全局范圍中。 這就是您無需導入即可使用MyApp.MyThing的原因。

// myapp.d.ts
declare namespace MyApp {
  interface MyThing {
    prop1: string;
    prop2: number;
  }
}

腳本的局限性在於它們不能導入任何東西; 當你添加一個import時,腳本就變成了一個模塊 我認為至少可以說很奇怪,但事實就是如此。 重要的是,模塊中定義的內容僅限於該模塊,而不是添加到全局范圍。

但是,模塊也可以將聲明添加到全局范圍,方法是將它們放在global中:

// myapp.d.ts
import {SomeType} from 'module';

declare global {
  namespace MyApp {
    interface MyThing {
      prop1: string;
      prop2: number;
      prop3: SomeType;
    }
  }
}

該文件是一個模塊,但它在全局范圍內添加了MyApp.MyThing的聲明,因此您仍然可以在其他 TypeScript 代碼中使用MyApp.MyThing而無需導入它。

請注意,使用.d.ts擴展名與您無需導入即可訪問界面無關。 上述兩個文件都可能是.ts文件,並且行為仍然完全相同。

從 TS 2.9 開始,這可以通過import()實現:

// myapp.d.ts
declare type SomeType = import('module').SomeType;
declare type SomeDefaultType = import('module-with-default-export').default;


declare namespace MyApp {
  interface MyThing {
    prop1: string;
    prop2: number;
    prop3: SomeType | SomeDefaultType;
  }
}

不知道您是否仍在尋找答案,但這是處理它的正確方法,並且仍然能夠例如定義通用模塊,而不僅僅是命名空間:( 基於原始答案)

// myapp.d.ts

declare namespace MyApp {
  import {SomeType} from 'module'
  interface MyThing {
    prop1: string
    prop2: number
    prop3: SomeType
  }
}

抱歉不行。 正如您已經發現的那樣,這只適用於內部代碼,例如沒有外部依賴項。 您應該導出命名空間,或者導出類並使用 ES6 模塊。 但兩者都會導致你需要import你的東西。 正如我所相信的那樣,您試圖避免的事情。

就個人而言,我發現在整個代碼中實際使用導入(甚至是內部)更令人欣慰。 原因很簡單,當打開特定文件(類)時,它的所有依賴項都立即可見。

“如何在 TypeScript 中使用帶有導入的命名空間”這個問題已經解決了一個完整的示例。

其他人請注意:“內部可用的命名空間”也是我不認為這是一個重復問題的原因。

就我而言,我有一個由電子創建的全局環境變量,用於 API 與節點進程交互。 我需要定義一個接口,其屬性類型從第三方依賴項而不是類型/接口中引用一個

TS 2.9 import() 語法在使用類型/接口而不是類時對我有用。 具體來說,我正在嘗試在我的界面中使用 rsjx.Observable 。 我能夠找到一種我在任何地方都沒有提到過的方法來處理這個問題。 我希望它可以幫助別人。

您可以通過使用要導出的類型創建模塊來組合模塊 + 環境,然后使用 TS 2.9 import() 語法將其拉入環境聲明中。

// types/electronAPI.ts
import { IpcRendererEvent } from 'electron'
import { Observable } from 'rxjs'

export type ThingStatus = 'on' | 'off'

export interface MyElectronAPI {
  thingObservable: Observable<[IpcRendererEvent, ThingStatus]>
}
// types/global.d.ts
declare type MyElectronAPI = import('./electronAPI').MyElectronAPI

const electronAPI: MyElectronAPI
// someFile.tsx

// I get all my types :)
elecronAPI.thingObservable.subscribe(([_e, status]) => { ... } )

暫無
暫無

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

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