[英]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.