iT邦幫忙

2023 iThome 鐵人賽

DAY 29
0

本篇只會稍微提到製作聲明文件的方式,並不會有過多深入的探討。

為什麼需要聲明文件?

有時候當我們使用第三方模組時,它們是依據純 JavaScript 來撰寫,這種程式碼通常不包含型別的聲明,這樣一來,TypeScript 便無法進行型別檢查,我們可能會遇到以下問題:

  • 編譯時錯誤檢測不足 可能導致在編譯時沒有錯誤提示,運行時才會出現 Bug。

  • 程式碼提示不足 沒有類型信息,所以編輯器沒有程式碼提示功能。

為了解決這些問題,所以我們才需要使用聲明文件。聲明文件以 .d.ts 為擴展名 ( d 的意思就是 declaration ),裡面只包含型別註解和型別定義。

因為 .d.ts 也是一個 Typescript 文件,所以我們需要到 tsconfig.json 去設定 include。例如威爾豬把 [聲明文件名稱].d.ts 放在和 tsconfig.json 同一層:

├── dist
├── src
|    └── app.ts
├── math.d.ts
└── tsconfig.json
"compilerOptions": {
    // ...
    "allowJs": true, // 允許 JS 引入和編譯輸出
    // ...
  },
  "include": ["src/**/*.ts", "./*.d.ts"] // 端看聲明文件要放哪來決定路徑

創建模組聲明文件

假設我們有一個純 JavaScript 的函式庫,它提供一個 add 函式來執行加法的操作:

// math.js

const add = (a, b) => a + b;

現在,我們希望在 TypeScript 項目中使用這個函式庫,我們可以創建一個聲明文件 math.d.ts,其中包含函式 add 的型別註解:

// math.d.ts

declare module "math" {
  export function add(a: number, b: number): number;
}

在聲明文件中使用 declare module 來描述模組的類型和對外的接口。

// app.ts

// 引入 math 模組
import { add } from "math";

add(2, "4"); // ❌ 錯誤 string 不可指派給 number 類型

現在,當我們在 TypeScript 中引入 math 模組時,TypeScript 將能夠識別並檢查 add 函式的型別,並提供相應的程式碼提示,確保程式碼的穩定性和可讀性。

https://ithelp.ithome.com.tw/upload/images/20230929/20141250oqF9mdyCgM.png

下載第三方資源的聲明文件

我們使用 Vue 官方 的方式來安裝 Vue 3 + Vite + TypeScript + Pinia。

npm create vue@latest

安裝完後打開 src/main.ts 就會發現,剛剛安裝的 vue 跟 pinia 出現找不到模組的錯誤。

https://ithelp.ithome.com.tw/upload/images/20230929/2014125040qJMVKlFO.png

這時我們可以透過 npm 使用 @typestypings 來尋找是否有可用的 TypeScript 聲明文件。

vue-types

npm install --save-dev @types/vue

# 或

npm i -D vue-types

安裝過程:

https://imgur.com/7i0955X.gif

這樣我們找不到模組的錯誤就消失了,通常較大的框架或模組都有提供相對應的聲明文件。

例如:reactreact-dom

npm install --save-dev @types/react @types/react-dom

所以,當我們安裝完 JavaScript 函式庫、框架和第三方模組時,發現有找不到模組的錯誤,就可以使用此方式來試著解決,但如果是一些比較小眾的套件可能就必須要自己創建了。

透過 @types 或 typings 的安裝方式,聲明文件會放置於 node_modules/@types 底下。

創建全域環境的聲明文件

全域環境可以聲明變數、函式、類別、命名空間、枚舉值、類型別名和接口等,這樣就可以在任一檔案中直接使用,TypeScript 會自動識別它們的類型。

看以下範例:

// globals.d.ts

// 聲明全域變數 (也可以使用 var、let)
declare const globalVariable: string;

// 聲明全域函式
declare function globalFunction(param1: number, param2: string): void;

// 聲明全域類別
declare class GlobalClass {
  constructor(public name: string);

  sayHi(): string;
}

// 聲明全域命名空間
declare namespace GlobalNamespace {
  let property1: number;
  let property2: string;
}

// 聲明全域枚舉值
declare enum GlobalEnum {
  property1,
  property2,
  property3,
}

// 聲明全域類型別名
declare type TGlobalType = number | string;

// 聲明全域接口
declare interface IGlobalInterface {
  property1: number;
  property2: string;
}

上面範例名稱、內容等都可自行依需求修改。


總之,聲明文件是 TypeScript 中的一個重要概念,它允許我們在使用 JavaScript 函式庫、框架或模組時,仍然能夠享受 TypeScript 的優勢,無論是簡單的模組還是複雜的函式庫等,聲明文件都能幫助我們更好地整合外部資源。因此當我們開始在 TypeScript 項目中使用第三方資源時,尋找適用的聲明文件來提供類型信息,使程式碼更加可靠、可讀並具有更好的程式碼提示。


上一篇
裝飾器 ( Decorators )
下一篇
前端開發環境 + React + TS
系列文
用不到 30 天學會基本 TypeScript30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言