【譯】TypeScript 類型聲明文件(.d.ts)編寫之深入(Definition File Theory: A Deep Dive)

通過結(jié)構(gòu)化模塊床未,為所需的 API 提供精確的原型并不是一件容易的事情烫映。例如:我們可能需要一個模塊在被調(diào)用時袱衷,帶上 new 關(guān)鍵字與不帶 new 關(guān)鍵字來生成不同的類型检吆,在層級關(guān)系中,暴露出不同的命名曹洽,并且還在模塊對象上具有一些屬性鳍置。

通過閱讀本指南,您將擁有編寫復(fù)雜定義文件的工具送淆,這些文件將提供友好的 API 表面税产。 本指南關(guān)注模塊(或 UMD)庫,因為這里的選項更多偷崩。

一砖第、關(guān)鍵概念(Key Concepts)

通過理解 TypeScript 的一些關(guān)鍵概念,您可以充分理解如何進(jìn)行任何形式的定義环凿。

1梧兼、類型(Types)

如果您正在閱讀本指南,您可能已經(jīng)大致了解 TypeScript 中的類型智听。 然而羽杰,再明確一下,一種類型可以通過以下形式被引入:

  • 類型別名聲明:type sn = number | string;
  • 接口聲明:interface I { x: number[]; }
  • 類聲明:class C { }
  • 枚舉聲明:enum E { A, B, C }
  • import 聲明指向一個類型

2到推、值(Values)

與類型一樣考赛,您可能已經(jīng)理解了什么是 Value。 Value 是我們可以在表達(dá)式中引用的運(yùn)行時名稱莉测。 例如:let x = 5; 創(chuàng)建一個名為 x 的 Value颜骤。
  明確一下通過以下形式創(chuàng)建 Value:

  • letconst捣卤、var 聲明
  • namespacemodule 聲明包含一個 Value
  • enum 聲明
  • class 聲明
  • import 聲明指向一個值
  • function 聲明

3忍抽、命名空間(Namespaces)

類型可以存在于命名空間中八孝。例如:有 let x: A.B.C 聲明,我們說類型 C 來自命名空間 A.B鸠项。
  這種區(qū)別是微妙重要的——在這里干跛,A.B 不一定是必要的類型或值。

二祟绊、簡單的組合:一個名字楼入,多重含義

給定一個名稱 A,我們可以為 A 找到三種不同的含義:一個類型牧抽,一個值或一個命名空間嘉熊。 名稱的解釋方式取決于其使用的上下文。 例如扬舒,在聲明 let m:A.A = A; 中阐肤,A 首先用作命名空間,然后用作類型名稱呼巴,然后用作值。 這些含義最終可能指的是完全不同的聲明御蒲!
  這看起來可能會讓人困惑衣赶,但只要我們不過分使用,它實際上非常方便厚满。 我們來看看這種組合行為的一些有用的方面府瞄。

1、內(nèi)建組合(Built-in Combinations)

精明的讀者會注意到碘箍,例如:class 同時出現(xiàn)在 typevalue 清單中遵馆。 聲明 class C {} 創(chuàng)建了兩項內(nèi)容:

  1. 類型 C——類 C 的實例原型
  2. C——類 C 的構(gòu)造函數(shù)

枚舉聲明的行為類似。

2丰榴、用戶組合(User Combinations)

假設(shè)我們寫了一個模塊文件 foo.d.ts

export var SomeVar: { a: SomeType };
export interface SomeType {
  count: number;
}

然后使用它:

import * as foo from './foo';
let x: foo.SomeType = foo.SomeVar.a;
console.log(x.count);

這工作得很好货邓,但我們可以想象 SomeTypeSomeVar 密切相關(guān),所以你希望它們有相同的名字四濒。 我們可以使用組合來以相同的名稱顯示這兩個不同的對象(值和類型)Bar

export var Bar: { a: Bar };
export interface Bar {
  count: number;
}

這為消費(fèi)代碼中的解構(gòu)提供了一個非常好的機(jī)會:

import { Bar } from './foo';
let x: Bar = Bar.a;
console.log(x.count);

同樣换况,我們在這里使用 Bar 同時作為類型和值。 請注意盗蟆,我們不必將 Bar的值聲明為 Bar 類型——它們是獨立的戈二。

三、高級組合(Advanced Combinations)

某些類型的聲明可以在多個聲明中組合使用喳资。 例如觉吭,class C { }interface C { } 可以共存,并且都為 C 類型提供屬性仆邓。

只要不產(chǎn)生沖突鲜滩,這是合法的伴鳖。 一般的經(jīng)驗法則是:

  • 總是與其他相同名稱的值沖突,除非它們被聲明為命名空間绒北;
  • 如果使用類型別名進(jìn)行聲明類型黎侈,如:type s = string,則可能會產(chǎn)生沖突闷游;
  • 命名空間永不沖突峻汉。

我們來看看如何使用它。

1脐往、使用 interface 添加(Adding using an interface

我們可以使用另一個 interface 聲明將其他成員添加到現(xiàn)有 interface 聲明中:

interface Foo {
  x: number;
}
// ... elsewhere ...
interface Foo {
  y: number;
}
let a: Foo = ...;
console.log(a.x + a.y); // OK

這也適用于類:

class Foo {
  x: number;
}
// ... elsewhere ...
interface Foo {
  y: number;
}
let a: Foo = ...;
console.log(a.x + a.y); // OK

請注意休吠,我們不能使用 interface 添加類型別名,如:type s = string;业簿。

2瘤礁、使用 namespace 添加(Adding using a namespace

namespace 聲明可用于以任何不會產(chǎn)生沖突的方式,添加新的類型梅尤、值和命名空間柜思。
例如,為類添加靜態(tài)成員:

class C {
}
// ... elsewhere ...
namespace C {
  export let x: number;
}
let y = C.x; // OK

請注意巷燥,在這個例子中赡盘,我們向 C 的靜態(tài)端(它的構(gòu)造函數(shù))添加了一個值。 這是因為我們添加了一個值缰揪,并且所有值的容器都是另一個值(類型由命名空間包含陨享,命名空間由其他命名空間包含)。

我們也可以為類添加一個命名空間類型:

class C {
}
// ... elsewhere ...
namespace C {
  export interface D { }
}
let y: C.D; // OK

在這個例子中钝腺,直到我們寫了命名空間聲明之前抛姑,沒有一個命名空間 CC 作為命名空間的含義艳狐,與該類創(chuàng)建的 C類型的含義不沖突定硝。

最后,我們可以使用命名空間聲明來執(zhí)行許多不同的合并毫目。 這不是一個特別實際的例子喷斋,但顯示了各種有趣的行為:

namespace X {
  export interface Y { }
  export class Z { }
}

// ... elsewhere ...
namespace X {
  export var Y: number;
  export namespace Z {
    export class C { }
  }
}
type X = string;

在本例中,第一個塊創(chuàng)建以下名稱含義:

  • X(因為 namespace 聲明包含了值 Z
  • 命名空間 X(因為 namespace 聲明包含了類型 Y
  • 類型 Y 在命名空間 X
  • 類型 Z 在命名空間 X 中(類的實例原型)
  • Z蒜茴,屬于 X 值的屬性(類的構(gòu)造器)

第二個塊創(chuàng)建以下名稱含義:

  • Ynumber 類型星爪,X 值的屬性)
  • 命名空間 Z
  • ZX 值的屬性)
  • 類型 C(在命名空間 X.Z 中)
  • CX.Z 值的屬性)
  • 類型 X

四、使用 export =import

一個重要的規(guī)則粉私,是 exportimport 聲明輸出或輸入它們目標(biāo)的所有含義顽腾。

五、參考資料

譯自 Definition File Theory: A Deep Dive

(完)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市抄肖,隨后出現(xiàn)的幾起案子久信,更是在濱河造成了極大的恐慌,老刑警劉巖漓摩,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件裙士,死亡現(xiàn)場離奇詭異,居然都是意外死亡管毙,警方通過查閱死者的電腦和手機(jī)腿椎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來夭咬,“玉大人啃炸,你說我怎么就攤上這事∽慷妫” “怎么了南用?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長掏湾。 經(jīng)常有香客問我裹虫,道長,這世上最難降的妖魔是什么融击? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任筑公,我火速辦了婚禮,結(jié)果婚禮上砚嘴,老公的妹妹穿的比我還像新娘十酣。我一直安慰自己涩拙,他們只是感情好际长,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著兴泥,像睡著了一般工育。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上搓彻,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天如绸,我揣著相機(jī)與錄音,去河邊找鬼旭贬。 笑死怔接,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的稀轨。 我是一名探鬼主播扼脐,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了瓦侮?” 一聲冷哼從身側(cè)響起艰赞,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎肚吏,沒想到半個月后方妖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡罚攀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年党觅,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坞生。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡仔役,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出是己,到底是詐尸還是另有隱情又兵,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布卒废,位于F島的核電站沛厨,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏摔认。R本人自食惡果不足惜逆皮,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望参袱。 院中可真熱鬧电谣,春花似錦、人聲如沸抹蚀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽环壤。三九已至晒来,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間郑现,已是汗流浹背湃崩。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留接箫,地道東北人攒读。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像辛友,于是被迫代替她去往敵國和親薄扁。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)泌辫,斷路器随夸,智...
    卡卡羅2017閱讀 134,651評論 18 139
  • Lua 5.1 參考手冊 by Roberto Ierusalimschy, Luiz Henrique de F...
    蘇黎九歌閱讀 13,783評論 0 38
  • "Unterminated string literal.": "未終止的字符串文本。", "Identifier...
    兩個心閱讀 8,364評論 0 4
  • { "Unterminated string literal.": "未終止的字符串文本震放。", "Identifi...
    Elbert_Z閱讀 10,829評論 0 2
  • 項目一:深蹲 12.5kg 15*4 項目二:硬拉 20kg 10*4 項目三:高抬腿 0kg 20*2宾毒; 5lb...
    oppy閱讀 162評論 0 0