如何手動補充陳年老庫(或純 JS 代碼)的 TypeScript 類型?

来源:https://www.cnblogs.com/onsummer/archive/2023/01/31/17080178.html
-Advertisement-
Play Games

這篇僅為自己工作中在 js 和 ts 交叉鬥智鬥勇的實踐中留下的經驗,不一定完全、合理,僅供參考,有錯漏難免,有則評論區指出。 前置知識 - JavaScript 的各種模塊化情況 全局模塊,在 globalThis 上可以訪問,一般是 iife 庫程式 ES 模塊 CommonJS 模塊 前置知識 ...


目錄


這篇僅為自己工作中在 js 和 ts 交叉鬥智鬥勇的實踐中留下的經驗,不一定完全、合理,僅供參考,有錯漏難免,有則評論區指出。

前置知識 - JavaScript 的各種模塊化情況

  • 全局模塊,在 globalThis 上可以訪問,一般是 iife 庫程式

  • ES 模塊

  • CommonJS 模塊

前置知識2 - 讓你寫的 d.ts 在工程中生效

  • 確保當前工程目錄中使用的 TypeScript 是 node_modules 下的開發依賴,快捷命令 Ctrl + Shift + P,選擇 TypeScript 版本即可

  • tsconfig.json 中配置 include 項,使得你寫的 d.ts 文件在 include 的路徑中即可

1. 全局模塊的定義

假設我有一個定義在 globalThis 上的庫,名叫 WebCC,它很簡單:

window.WebCC = (function(){
  const foo = () => {
    console.log('foo')    
  }
  const bar = 'bar'
  const NAME = 'WebCC'
  return {
    foo,
    bar,
    NAME
  }
})()

那麼,它應該使用 namespace 來定義:

declare namespace WebCC {
  function foo(): void
  const bar: string
  const NAME: string
}

2. ES 模塊的定義

仍以上述 WebCC 這個名字為例,但是這次是 ES 模塊:

// webcc.js
export const bar = 'bar'
export const NAME = 'WebCC'
export const foo = () => {
  console.log('foo')
}

那麼,它應該使用 module 來定義:

// webcc.d.ts
declare module 'webcc' {
  export const bar: string
  export const NAME: string
  export const foo: () => void
}

module 關鍵字後面的模塊名即 import 時的模塊名:

import { foo } from 'webcc'

2.1. 預設導出

declare module 'webcc' {
  const XXX: string
  export default XXX
}

2.2. 導出類

declare module 'webcc' {
  export class Foo {
    /** 構造器 */
    constructor()
    /** 欄位成員,類型為函數 */
    foo: () => void
    /** 欄位成員,類型為 string */
    NAME: string
    /** 函數成員 */
    bar(): void
    /** 靜態欄位成員,類型為 number */
    static VERSION: number
  }
}

2.3. 註意事項

在模塊聲明的 d.ts 文件中,想引入其他模塊的定義,不能像模塊一樣使用 import 指令,而是要使用 import()。例如,想在 parser.d.ts 中引入別人已經定義好的數據類型,來自 @types/fooFoo 類型,那麼要寫成:

declare module 'my-parser' {
  export parse(val: import('foo').Foo): string
}

這是因為一旦在代碼文件頂部寫了 import 就會被當作模塊文件,而不是類型聲明文件。這個特性來自 TS 2.9 版本。

3. CommonJS 模塊定義

CommonJS 的模塊聲明與 ES 模塊聲明大同小異,即 module.exports.foo(或簡寫 exports.foo)對應 export foomodule.exports = foo 對應 export default foo

3.1. 挨個導出

module.exports = {
  foo: function() {
    console.log('foo')  
  },
  bar: "bar"
}

類型聲明為:

declare module 'webcc' {
  export const foo: () => void
  export const bar: string
}

3.2. 預設導出

module.exports = class WebCC {
  foo() {
    console.log('foo')   
  }
}

類型聲明為:

declare module 'webcc' {
  export default class WebCC {
    foo(): void
  }
}

4. 聲明類型(TypeScript 中的 interface 或 type)和其它

4.1. type 和 interface

滿足前置知識2 的前提下,在任意 d.ts 中書寫的 interfacetype 定義均可被整個項目使用:

declare type WebCCOptions = {
  foo: string
  bar: boolean
}
declare interface WebCCResponse {
  foo: string
}

4.2. 全局變數(非 namespace)

全局變數也可以如法炮製:

declare const WebCC: {
  foo: () => void
}

4.3. 補充功能

例如,想為原生數組補充一個新的函數成員 foo,先在某些地方實現:

// somefile.js
Array.prototype.foo = function() {
  console.log('foo')
}

這個時候需要補齊這個類型:

// somefile.d.ts
declare interface Array<T> {
  foo(): void
}

有的讀者可能不知道為什麼 Array 是 interface,那是因為這個是官方的定義,我只是點了點 F12 ... 畢竟 interface 才能繼續補充定義,官方的 d.ts 更完善、強大,建議自學。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.背景知識 CRLF用來表示文本換行的方式 ,CR是回車的意思,對應 \r ;LF 是換行的意思,對應 \n Windows 換行符是 \r\n Unix 換行是 \n 如果一個將要在Linux伺服器上使用的文件,比如某個配置文件,在windows電腦打開,編輯過,那麼文件每一行末尾會多有\r 。 ...
  • MySQL中既存在redo log,又存在bin log,這是因為bin log是MySQL Server提供的一種歸檔日誌,其本身並不具備crash-safe能力。而redo log本身不具備歸檔能力,他是一種迴圈寫的日誌。 MySQL通過將這兩種日誌整合起來,並通過兩階段提交的機制,保證了數據... ...
  • 一:背景 1. 講故事 相信絕大部分用 SQLSERVER 作為底層存儲的程式員都知道 nolock 關鍵詞,即使當時不知道也會在踩過若幹阻塞坑之後果斷的加上 nolock,但這玩意有什麼註意事項呢?這就需要瞭解它的底層原理了。 二:nolock 的原理 1. sql 阻塞還原 為了方便講述,先創建 ...
  • Redis 每秒可以處理超過 10 萬次讀寫操作,是已知性能最快的 key-value 資料庫,稱得上是必須要學會的知識。 ...
  • 華為 HMS Core 音頻編輯服務(Audio Editor Kit)是華為幫助全球開發者快速構建各類應用音頻能力的服務,匯聚了華為在音樂、語音等相關音頻領域的先進技術。音頻編輯服務為開發者們提供音頻基礎編輯、AI配音、音源分離、空間渲染、變聲、多種音效等豐富的音頻處理能力,以及性能優異、簡單易用 ...
  • 一、前言 你可以使用任意文本編輯器,再結合命令行工具來開發 Flutter 應用。然而,我們推薦使用本文接下來介紹的編輯器插件以獲取更好的開發體驗。這些插件提供了代碼補全、代碼高亮、widget 輔助編輯的功能,以及為項目的運行和調試提供支持等。 推薦的開發工具有 VS Code、Android S ...
  • 隨著移動互聯網的高速發展,各家大廠的小程式百花齊放,在用戶規模及商業化方面都取得了極大的成功。微信小程式的日活超過5億,其他追趕者如:支付寶、百度、位元組跳動小程式的月活也紛紛超過3億。鑒於小程式相比App,無需下載等待,有更高的激活率,相比H5有更好的下單轉化率,汽車報價業務線藉助各平臺的優勢,大力... ...
  • 我們是袋鼠雲數棧 UED 團隊,致力於打造優秀的一站式數據中台產品。我們始終保持工匠精神,探索前端道路,為社區積累並傳播經驗價值。 相容性問題 第三方依賴相容問題 React - 最低 v16.9,部分組件使用 hooks 重構 react升級相關文檔 Less - 最低 v3.1.0,建議升級到 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...