TypeScript系列?尾聲篇, 什麼是宣告檔案(declare)? [?全域性宣告篇]

鐵皮飯盒發表於2019-11-13

往期目錄

第一課, 體驗typescript

第二課, 基礎型別和入門高階型別

第三課, 泛型

第四課, 解讀高階型別

第五課, 名稱空間(namespace)是什麼

特別篇, 在vue3?原始碼中學會typescript? - "is"

第六課, 什麼是宣告檔案(declare)? ? - 全域性宣告篇

全域性宣告篇

年底比較忙?, 受個人時間限制, 暫把"宣告"部分的內容分為"全域性宣告篇"和"模組宣告篇", ?還請多多包涵, 本次先說"全域性".

什麼是宣告檔案?

宣告檔案就是給js程式碼補充型別標註. 這樣在ts編譯環境下就不會提示js檔案"缺少型別".

宣告變數使用關鍵字declare來表示宣告其後面的全域性變數的型別, 比如:

// packages/global.d.ts
declare var __DEV__: boolean
declare var __TEST__: boolean
declare var __BROWSER__: boolean
declare var __RUNTIME_COMPILE__: boolean
declare var __COMMIT__: string
declare var __VERSION__: string
複製程式碼

看過vue3原始碼的同學一定知道這些是vue中的變數, 上面程式碼表示__DEV__等變數是全域性, 並且標註了他們的型別. 這樣無論在專案中的哪個ts檔案中使用__DEV__, 變數ts編譯器都會知道他是boolean型別.

宣告檔案在哪裡?

首先宣告檔案的檔名是有規範要求的, 必須以.d.ts結尾, 看了上面的程式碼你肯定想練習寫下宣告檔案, 但是你可能想問了"寫完放在哪裡", 網上說宣告檔案放在專案裡的任意路徑/檔名都可以被ts編譯器識別, 但實際開發中發現, 為了規避一些奇怪的問題, 推薦放在根目錄下.

1.png

別人寫好的宣告檔案( @types/xxx )

一般比較大牌的第三方js外掛在npm上都有對應的宣告檔案, 比如jquery的宣告檔案就可以在npm上下載:

npm i @types/jquery
複製程式碼

npm i @types/jquery中的jquery可以換成任意js庫的名字, 當然前提是有人寫了對應的宣告檔案釋出到了npm.

安裝後, 我們可以在node_modules/@types/jquery中的看到宣告檔案, 這裡我開啟mise.d.ts檔案:

TypeScript系列?尾聲篇, 什麼是宣告檔案(declare)? [?全域性宣告篇]

宣告檔案對純js專案有什麼幫助?

即便你只寫js程式碼, 也可以安裝宣告檔案, 因為如果你用的是vscode, 那麼他會自動分析js程式碼, 如果存在對應的宣告檔案, vscode會把宣告檔案的內容作為程式碼提示.

jquery在安裝了宣告檔案後

1.png

什麼情況下要自己寫宣告檔案?

如果"@types/"下找不到宣告檔案, 那麼就需要我們自己手寫了.

?如何寫宣告檔案?

宣告檔案分2大類, 一類是全域性宣告, 一類是對模組的宣告. 這節只說"全域性".

全域性宣告

通過declare我們可以標註js全域性變數的型別.

簡單應用

// global.d.ts
declare var n: number;
declare let s: string;
declare const o: object;
declare function f(s: string): number;
declare enum dir {
    top,
    right,
    bottom,
    left
}
複製程式碼

宣告之後,我們就可以在任意檔案中直接操作變數:

n = 321
s = '文字'
let o1 = o;
f('123').toFixed();
dir.bottom.toFixed();

// 報錯
n = '312'
s = 123
複製程式碼

declare namespace

這個namespace代表後面的全域性變數是一個物件:

// global.d.ts
declare namespace MyPlugin {
    var n:number;
    var s:string;
    var f:(s:string)=>number;
}
複製程式碼
MyPlugin.s.substr(0,1);
MyPlugin.n.toFixed();
MyPlugin.f('文字').toFixed();

// 報錯
MyPlugin.s.toFixed();
MyPlugin.n.substr(0,1);
MyPlugin.f(123);
複製程式碼

修改已存在的全域性宣告

其實我們安裝完typescript, 會自動給我們安裝一些系統變數的宣告檔案, 存在node_modules/typescript/lib下.

TypeScript系列?尾聲篇, 什麼是宣告檔案(declare)? [?全域性宣告篇]

如果你要修改已存在的全域性變數的宣告可以這麼寫, 下面用node下的global舉例,

declare global {
    interface String {
        hump(input: string): string;
    }
}
// 注意: 修改"全域性宣告"必須在模組內部, 所以至少要有 export{}字樣
// 不然會報錯❌: 全域性範圍的擴大僅可直接巢狀在外部模組中或環境模組宣告中
export {}
複製程式碼

現在String型別在vscode的語法提示下多了一個hump的方法,不過我們只是宣告, 並沒有用js實現, 所以執行會報錯, 所以不要忘了寫js的實現部分哦.

1.png

總結

年底真是比較忙, 但是之前答應了更新ts的內容, 所以只能一步步完成"宣告"部分的內容, 還請見諒?.

多寫多練, 很快就上手, 放幾個我用ts寫的專案當做參考, 拋磚引玉, 加油!

✋ 移動/pc端手勢庫, 支援: tap/press/pan/swipe/rotate/pinch

github.com/any86/any-t…

? 把vue元件變成this.$xxx這樣的命令

github.com/any86/vue-c…

微信群

感謝大家的閱讀, 如有疑問可以加我微信, 我拉你進入微信群(由於騰訊對微信群的100人限制, 超過100人後必須由群成員拉入)

TypeScript系列?尾聲篇, 什麼是宣告檔案(declare)? [?全域性宣告篇]

相關文章