徹底搞懂 Typescirpt 聲明文件

為什么需要聲明文件

初始化項目

$ mkdir test-declare 
$ cd test-declare
$ npm init -y
$ yarn add typescript -D
$ npx tsc --init

創(chuàng)建 src/sum/index.js 文件岩四,內(nèi)容如下:
這是一個最普通不過的 js 文件,對外暴露 sum() 方法哥攘,在 nodejs 中運行剖煌。

function sum(a, b) {
    return a + b
}

module.exports = sum

創(chuàng)建 src/index.ts 文件,內(nèi)容如下:
(這是一個 ts 文件逝淹,在 ts 文件中導(dǎo)入 js 文件)

import sum from './sum'

console.log(sum(2, 2))

這時耕姊,如果使用 Vscode 編輯代碼,應(yīng)該可以看到如下的報錯:意思就是沒找到 sum 文件的聲明文件栅葡。

圖1

為什么會報這個錯誤茉兰?

typescript 編譯器看到的每個變量、方法都必須明確知道它的類型妥畏,在 src/index.ts 文件中導(dǎo)入 src/sum/index.js 文件邦邦,js 文件中的方法是沒有類型的,造成 typescript 不能識別的錯誤醉蚁。

解決方法也很簡單燃辖,編輯 tsconfig.json 文件:

"allowJs": true,
"outDir": "./dist",
"rootDir": "./src",

其中 allowJs 配置告訴 typescript 編輯器將 js 文件中的所有變量和方法都設(shè)置 any 類型,這樣 typescript 編譯器就能識別 js 文件了网棍。

添加配置后報錯消失黔龟,鼠標移動到 sum() 方法可以看到方法參數(shù)確確實實都設(shè)置為 any 類型了。

圖2

此時目錄結(jié)構(gòu)應(yīng)該如下:

|-- test-declare
    |-- src
        |-- sum
            |-- index.js
        |-- index.ts
    |-- package.json
    |-- tsconfig.json

編譯代碼

打開黑窗口滥玷,編譯代碼氏身,編譯完成后根目錄下會生成 dist 目錄。

$ npx tsc -w

啟動程序

另外打開一個黑窗口惑畴,運行程序蛋欣,可以看到打印出計算結(jié)果。

$ node dist/index.js
$ 4

雖然 ts 文件中可以導(dǎo)入 js 文件如贷,并正常運行程序陷虎,但但但但但但是,js 文件的方法類型全是 any 很惡心杠袱。

我們希望為 js 文件里的變量和方法添加真實的類型尚猿,這就需要定義聲明文件。

定義類型聲明文件

創(chuàng)建 src/sum/index.d.ts 文件楣富,內(nèi)容如下:

declare function sum(a: number, b: number): number

export default sum

此時再查看 src/index.ts 文件凿掂,可以看到導(dǎo)入的 sum() 方法的參數(shù)已經(jīng)有類型提示了。??

圖3

此時目錄結(jié)構(gòu)為:

|-- test-declare
    |-- src
        |-- sum
            |-- index.js
            |-- index.d.ts      <=== 類型聲明文件
        |-- index.ts
    |-- package.json
    |-- tsconfig.json

給第三方庫寫聲明文件

很多第三方庫是用 js 寫的纹蝴,通過設(shè)置 allowJs: true 配置可以在 typescript 工程使用這些庫庄萎,但是沒法知道庫里面變量的類型以及方法參數(shù)的類型,很不友好骗灶。

我們期待:在 Vscode 開發(fā)時惨恭,只要敲出方法,編輯器可以自行提示該方法參數(shù)的類型是什么耙旦,這樣我就不會把原本該寫成數(shù)值類型的參數(shù)寫成字符串類型了脱羡,大大降低代碼出錯風險。

圖4

如果你是第三方庫作者

如果您是第三方庫的作者免都,我們希望您在自己的庫里就添加上聲明文件锉罐。

手動創(chuàng)建 node_modules/subtract 模擬第三方庫,切換到 subtract 目錄下執(zhí)行 $ npm init -y 初始化 subtract 工程绕娘。

|-- test-declare
    |-- node_modules   <=== 手動創(chuàng)建 subtract 模擬第三方庫 
        |-- subtract
            |-- src
                |-- index.js
            |-- index.d.ts
            |-- package.json
    |-- src
    |-- ....

編輯 node_modules/subtract/src/index.js 文件脓规,內(nèi)容如下:

function subtract(a, b) {
    return a - b
}

module.exports = subtract

編輯 node_modules/subtract/index.d.js 文件,內(nèi)容如下:

declare function subtract(a: number, b: number): number

export default subtract

修改 package.json 文件险领,其中 types 指向聲明文件路徑侨舆。

"main": "./src/index.js",
"types": "./index.d.ts",

實測發(fā)現(xiàn)秒紧,外部庫找第三方庫聲明文件默認路徑為第三方庫(subtract)根目錄下的 index.d.ts 文件,找不到的話挨下,會去找第三方庫 package.json 中 types 字段中設(shè)置的路徑熔恢。

編輯 src/index.ts 文件,導(dǎo)入 subtract 庫并執(zhí)行方法臭笆,鼠標移動到 subtract() 方法上叙淌,可以看到也是有參數(shù)類型提示的,測試成功愁铺。

圖5

如果你是第三方庫的使用者

如果您是第三方庫的使用者鹰霍,您是沒法直接修改第三方庫的源碼,只能改自己的代碼茵乱。

手動創(chuàng)建 node_modules/multiply 模擬第三方庫茂洒,切換到 multiply 目錄下執(zhí)行 $ npm init -y 初始化 multiply 工程。

|-- test-declare
    |-- node_modules   <=== 手動創(chuàng)建 multiply 模擬第三方庫 
        |-- multiply
            |-- index.js
            |-- package.json
    |-- src
    |-- ....

編輯 test-declare/node_modules/multiply/index.js 文件:

function multiply(a, b) {
    return a * b
}

module.exports = multiply

修改 test-declare/src/index.ts 文件瓶竭,導(dǎo)入 multiply 模塊获黔,可以看到報錯:沒有找到 multiply 模塊的聲明文件。

圖7

報錯信息也提供了兩種解決方案:

  • npm install @types/multiply 這種方案前提是有人已經(jīng)寫好了聲明文件在验,我們可以直接安裝下就哦了玷氏;
  • add a new declaration(.d.ts) file containing "declare module multiply" 如果沒有 @types/multiply 包,還可以在根目錄下新建 global.d.ts腋舌,內(nèi)容寫上 declare module 'multiply'盏触。這樣做只能保證代碼不報錯,但是鼠標移動到 multiply 上面是沒有參數(shù)類型提示的块饺,這明顯不是我們想要的赞辩。
圖8

(如果前面創(chuàng)建了 global.d.ts,刪除它)

創(chuàng)建 test-declare/types/multiply/index.d.ts 文件寫聲明文件授艰,types 下目錄的名字一定要和第三方庫的名字一毛一樣辨嗽,這里為第三方庫 multiply 寫聲明文件,因此創(chuàng)建 types/multiply 目錄淮腾。

declare function multiply(a: number, b: number): number

export default multiply

編輯 tsconfig.json 文件糟需,告訴 typescirpt 去哪里找我們自己定義的聲明文件。

"baseUrl": "./",
"paths": {
    "*": [ "types/*" ]
}, 

回過頭看下 src/index.ts 文件谷朝,multiply() 方法的參數(shù)類型已經(jīng)可以顯示了洲押。

圖9

此時目錄結(jié)構(gòu)為:

|-- test-declare
    |-- ...
    |-- src
    |-- types
        |-- multiply
            |-- index.d.ts        <=== 聲明文件
    |-- ....

如何寫聲明文件

還剩最后一個話題,如何編寫聲明文件圆凰,這需要掌握 Typescript 基本語法杈帐。

導(dǎo)出一個方法

上面??寫的所有聲明方法都是對外暴露一個方法,暴露變量類似。

源碼 index.js

function divide (a, b) {
    return a / b
}

為 index.js 編寫聲明文件:

// index.d.ts
declare function divide(a: number, b: number): number
export default divide

導(dǎo)出一個對象字面量

想要導(dǎo)出一個對象字面量挑童,這個對象字面量內(nèi)包含了很多方法和變量累铅,如何做?

源碼 my-math.js

function multiply(a, b) {
    return a * b
}

function divide(a, b) {
    return a / b
}

const num1 = 4
const num2 = 2

module.exports = {
    multiply, divide, num1, num2
}

使用 namespace 對外導(dǎo)出一個對象字面量站叼,對應(yīng)的聲明文件:

// index.d.ts
declare namespace obj {
    function multiply(a: number, b: number): number
    function divide(a: number, b: number): number
    const num1: number
    const num2: number
}

export default obj

使用:

// index.ts
import math from 'multiply'
console.log(math.multiply(math.num1, math.num2))
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末争群,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子大年,更是在濱河造成了極大的恐慌,老刑警劉巖玉雾,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件翔试,死亡現(xiàn)場離奇詭異,居然都是意外死亡复旬,警方通過查閱死者的電腦和手機垦缅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來驹碍,“玉大人壁涎,你說我怎么就攤上這事≈就海” “怎么了怔球?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長浮还。 經(jīng)常有香客問我竟坛,道長,這世上最難降的妖魔是什么钧舌? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任担汤,我火速辦了婚禮,結(jié)果婚禮上洼冻,老公的妹妹穿的比我還像新娘崭歧。我一直安慰自己,他們只是感情好撞牢,可當我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布率碾。 她就那樣靜靜地躺著,像睡著了一般屋彪。 火紅的嫁衣襯著肌膚如雪播掷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天撼班,我揣著相機與錄音歧匈,去河邊找鬼。 笑死砰嘁,一個胖子當著我的面吹牛件炉,可吹牛的內(nèi)容都是我干的勘究。 我是一名探鬼主播,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼斟冕,長吁一口氣:“原來是場噩夢啊……” “哼口糕!你這毒婦竟也來了祭衩?” 一聲冷哼從身側(cè)響起演熟,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎仓犬,沒想到半個月后秀撇,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體超棺,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年呵燕,在試婚紗的時候發(fā)現(xiàn)自己被綠了棠绘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡再扭,死狀恐怖氧苍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情泛范,我是刑警寧澤让虐,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站罢荡,受9級特大地震影響澄干,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜柠傍,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一麸俘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧惧笛,春花似錦从媚、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至各谚,卻和暖如春紧憾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背昌渤。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工赴穗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓般眉,卻偏偏與公主長得像了赵,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子甸赃,可洞房花燭夜當晚...
    茶點故事閱讀 44,884評論 2 354

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

  • 點擊原文 now我們來看一看TS怎么聲明文件柿汛, 在JS里面我們經(jīng)常會使用各種第三方類庫,引入方式也不太相同埠对,常見的...
    videring閱讀 3,123評論 0 4
  • 當使用第三方庫時络断,我們需要引用它的聲明文件,才能獲得對應(yīng)的代碼補全项玛、接口提示等功能貌笨。這是因為前端第三方庫大多都是非...
    CondorHero閱讀 4,898評論 1 5
  • 為TypeScript引用的JS寫聲明文件 寫TypeScript聲明文件的時候會有三個困惑,一個是聲明文件是什么...
    心淡然如水閱讀 25,239評論 1 2
  • core package 概要:Core是所有其他包的基礎(chǔ)包.它提供了大部分功能包括metadata稍计,templa...
    LOVE小狼閱讀 2,579評論 0 3
  • 為什么要使用TS? 獲得更好的開發(fā)體驗裕循,解決JS中一些難以解決的問題 JS存在的問題: 使用了不存在的變量函數(shù)或者...
    小丹子1o1閱讀 700評論 0 0