現在您已按照本指南的步驟撰寫宣告檔案,是時候將其發布到 npm 了。您可以透過兩種主要方式將宣告檔案發布到 npm
- 與您的 npm 套件綑綁
- 發布到 npm 上的 @types 組織。
如果您的類型是由您的原始碼產生的,請將類型與您的原始碼一起發布。TypeScript 和 JavaScript 專案都可以透過 declaration
產生類型。
否則,我們建議將類型提交給 DefinitelyTyped,它會將類型發布到 npm 上的 @types
組織。
在 npm 套件中包含宣告
如果您的套件有一個主 .js
檔案,您也需要在 package.json
檔案中指出主宣告檔案。將 types
屬性設定為指向您的已套件化宣告檔案。例如
json
{"name": "awesome","author": "Vandelay Industries","version": "1.0.0","main": "./lib/main.js","types": "./lib/main.d.ts"}
請注意,"typings"
欄位與 types
同義,也可以使用。
相依性
所有相依性都由 npm 管理。請確定您依賴的所有宣告套件都已在 package.json
的 "dependencies"
區段中適當地標記。例如,假設我們撰寫了一個使用 Browserify 和 TypeScript 的套件。
json
{"name": "browserify-typescript-extension","author": "Vandelay Industries","version": "1.0.0","main": "./lib/main.js","types": "./lib/main.d.ts","dependencies": {"browserify": "latest","@types/browserify": "latest","typescript": "next"}}
在此,我們的套件依賴於 browserify
和 typescript
套件。browserify
沒有將其宣告檔案與其 npm 套件一起套件化,因此我們需要依賴 @types/browserify
來取得其宣告。另一方面,typescript
會套件化其宣告檔案,因此不需要任何其他相依性。
我們的套件公開了來自每個套件的宣告,因此我們 browserify-typescript-extension
套件的任何使用者也需要有這些相依性。因此,我們使用 "dependencies"
而不是 "devDependencies"
,否則我們的使用者將需要手動安裝這些套件。如果我們只是撰寫一個命令列應用程式,而不是預期我們的套件會被用作函式庫,我們可能會使用 devDependencies
。
警示
/// <reference path="..." />
不要在宣告檔案中使用 /// <reference path="..." />
。
ts
/// <reference path="../typescript/lib/typescriptServices.d.ts" />....
請改用 /// <reference types="..." />
。
ts
/// <reference types="typescript" />....
請務必重新檢閱 消耗相依性 部分以取得更多資訊。
封裝相依宣告
如果您的類型定義相依於其他套件
- 不要將其與您的類型定義合併,請將每個類型定義保留在自己的檔案中。
- 不要複製套件中的宣告。
- 請相依於 npm 類型宣告套件,如果它未封裝其宣告檔案。
使用 typesVersions
進行版本選取
當 TypeScript 開啟一個 package.json
檔案以找出它需要讀取哪些檔案時,它首先會查看一個名為 typesVersions
的欄位。
資料夾重新導向(使用 *
)
具有 typesVersions
欄位的 package.json
可能如下所示
json
{"name": "package-name","version": "1.0.0","types": "./index.d.ts","typesVersions": {">=3.1": { "*": ["ts3.1/*"] }}}
此 package.json
告訴 TypeScript 首先檢查 TypeScript 的目前版本。如果是 3.1 或更新版本,TypeScript 會找出您相對於套件匯入的路徑,並從套件的 ts3.1
資料夾中讀取。
這就是 { "*": ["ts3.1/*"] }
的意思 - 如果你熟悉 路徑對應,它的運作方式完全相同。
在上述範例中,如果我們從 "package-name"
匯入,TypeScript 會嘗試在 TypeScript 3.1 中執行時從 [...]/node_modules/package-name/ts3.1/index.d.ts
(和其他相關路徑)解析。如果我們從 package-name/foo
匯入,我們會嘗試尋找 [...]/node_modules/package-name/ts3.1/foo.d.ts
和 [...]/node_modules/package-name/ts3.1/foo/index.d.ts
。
如果我們不在此範例中執行 TypeScript 3.1 呢?好吧,如果 typesVersions
中沒有任何欄位相符,TypeScript 會回退到 types
欄位,因此這裡的 TypeScript 3.0 和更早版本將重新導向到 [...]/node_modules/package-name/index.d.ts
。
檔案重新導向
當您只想變更單一檔案的解析度時,您可以透過傳入確切的檔案名稱來告訴 TypeScript 以不同的方式解析檔案
json
{"name": "package-name","version": "1.0.0","types": "./index.d.ts","typesVersions": {"<4.0": { "index.d.ts": ["index.v3.d.ts"] }}}
在 TypeScript 4.0 及以上版本中,"package-name"
的匯入將解析為 ./index.d.ts
,而在 3.9 及以下版本中則解析為 "./index.v3.d.ts
。
請注意,重新導向僅影響套件的外部 API;專案內的匯入解析不受 typesVersions
影響。例如,前一個範例中的 d.ts
檔案包含 import * as foo from "./index"
仍會對應到 index.d.ts
,而不是 index.v3.d.ts
,而匯入 import * as foo from "package-name"
的另一個套件將取得 index.v3.d.ts
。
比對行為
TypeScript 決定編譯器和語言版本是否相符的方式是使用 Node 的 semver 範圍。
多個欄位
typesVersions
可以支援多個欄位,其中每個欄位名稱由要比對的範圍指定。
{"name": "package-name","version": "1.0"," ": "./index.d.ts","typesVersions": {">=3.2": { "*": ["ts3.2/*"] },">=3.1": { "*": ["ts3.1/*"] }}}
由於範圍有可能重疊,因此決定套用哪個重新導向具有特定順序。這表示在上述範例中,即使 >=3.2
和 >=3.1
比對器都支援 TypeScript 3.2 及以上版本,但反轉順序可能會產生不同的行為,因此上述範例不等於以下範例。
{"name": "package-name","version": "1.0"," ": "./index.d.ts","typesVersions": {// NOTE: this doesn't work!">=3.1": { "*": ["ts3.1/*"] },">=3.2": { "*": ["ts3.2/*"] }}}
發佈至 @types
@types 組織下的套件會使用 types-publisher 工具 從 DefinitelyTyped 自動發佈。若要將您的宣告發佈為 @types 套件,請向 DefinitelyTyped 提交拉取要求。您可以在 貢獻指南頁面 找到更多詳細資訊。