TypeScript -- 如何處理第三方庫的型別

小紅星閃啊閃發表於2021-11-05

原文地址

我們使用開發TypeScript專案的時候或多或少都要用到第三方庫。一般常用的第三方庫都有對應的型別檔案,或者可以新增型別包。但是如果這個第三方庫沒有對應的型別檔案可以用就會稍有麻煩。今天就來探討一下這些都是怎麼處理的。

第一種:第三方庫是TypeScript開發的

這是最好的情況,自帶型別。使用TypeScript開發的庫在發到npm之前就編譯為JS了,這樣可以直接在瀏覽器和node環境下執行。同時,在內部使用呢的型別也一起打包釋出到npm了。這些型別在index.d.ts檔案,最終在node_modules下的專案目錄裡。

比如,react-content-loader是用TypeScript開發的,最終它的型別檔案在node_modules/react-content-loader目錄下。

這樣的開發方式還有一個好處,那就是這些型別會和程式碼的變動同步。因為型別都是從實際的程式碼中編譯得來的。

可惜並不是所有專案都是TypeScript開發的。遇到這樣的庫很多的好處都沒有了,比如智慧提示。。。那麼應該怎麼辦呢。

第二種:第三方庫有@types型別檔案

很多第三方庫不是用TypeScript開發的。這種情況可以使用DefinitelyTyped的方式類實現。有一個github庫:DefnitelyTyped。這裡就是用來儲存型別檔案的。所以第三方JS庫的型別檔案可以放在這裡。比如React,可以用@types/reactstyled-component可以用@types/styled-component

這些型別都是社群維護的,也就是說使用這些庫的人在維護這些庫的型別。雖然不是完全的不可控,還是有人會review這些型別檔案。但是,難免的是這些型別不能和庫一起演進,進而出現型別和庫不匹配的情況。畢竟庫本身並不支援型別。

第三種:第三方庫沒有型別檔案,也不是TypeScript開發的

TypeScript新建自己的型別非常簡單。TypeScript預設的從node_modules目錄的@types子目錄,還有index.d.ts檔案獲取型別。也就是說你可以在你專案的任意位置建一個index.d.ts檔案,新增型別。也可以在types目錄下維護型別。

index.d.ts檔案裡,你可以定義你專案裡的所有型別。記得把型別定義在特定的模組或者namespace下。比如:

declare module 'babel-plugin-relay/macro' {
  export { graphql as default } from 'react-relay';
}

因為這個庫要這麼用:

import graphql from 'babel-plugin-relay/macro';

monkeypatch

有時候在DefinitelyType,也就是@types/some-lib的型別是錯的。要搞定這個錯誤就只能用monkeypatch了。其實這樣也不是一個好主意,最好是給DefinitlyType提一個pr。但是這樣沒那麼快生效。所以只能走monkeypatch。

開頭也是一樣,新建一個index.d.ts檔案來存放某個庫的型別。在這個檔案裡宣告你要處理的模組或者namespace。然後在這個模組裡新的型別。然後,你要覆蓋掉錯誤的型別,你要先import以前的型別。比如現在有@testing-library/react-hooks

// inside types/testing-library__react-hooks/index.d.ts
import "@testing-library/react-hooks"

declare module "@testing-library/react-hooks" {
  interface RenderHookResult {
    // This function is not included in the typings as of 3.2.1
    wait(
      callback: (...args: any[]) => any,
      options?: { timeout?: number; suppressErrors?: boolean },
    ): Promise<void>
  }
}

現在@testing-library/react-hooks不僅包含了原始的型別,也包含了新方法的型別定義。

最後

第三方型別非常重要,本文也說明了我們專案裡的型別是如何處理的。一個穩定,與時俱進的型別是選擇第三方庫的重要指標,因為準確的型別可以極大的幫助開發。如果一個庫沒有型別定義,TypeScript也一樣提供了一種機制來處理。

相關文章