如何手動補充陳年老庫(或純 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
  • MQTTnet 是一個高性能的MQTT類庫,支持.NET Core和.NET Framework。 MQTTnet 原理: MQTTnet 是一個用於.NET的高性能MQTT類庫,實現了MQTT協議的各個層級,包括連接、會話、發佈/訂閱、QoS(服務質量)等。其原理涉及以下關鍵概念: MqttCli ...
  • 在WPF中,源屬性(Source Property)指的是提供數據的屬性,通常是數據模型或者其他控制項的屬性,而目標屬性(Target Property)則是數據綁定的目標,通常是綁定到控制項的屬性,例如TextBlock的Text屬性。數據綁定將源屬性的值自動更新到目標屬性中。 主要包含以下幾個事件: ...
  • async/await 是 C# 中非同步編程的關鍵特性,它使得非同步代碼編寫更為簡單和直觀。下麵深入詳細描述了 async/await 的使用場景、優點以及一些高級使用方法,並提供了相應的實例源代碼。 使用場景: I/O 操作: 非同步編程特別適用於涉及 I/O 操作(如文件讀寫、網路請求等)的場景。在 ...
  • 使用過office的visio軟體畫圖的小伙伴都知道,畫圖軟體分為兩部分,左側圖形庫,存放各種圖標,右側是一個畫布,將左側圖形庫的圖標控制項拖拽到右側畫布,就會生成一個新的控制項,並且可以自由拖動。那如何在WPF程式中,實現類似的功能呢?今天就以一個簡單的小例子,簡述如何在WPF中實現控制項的拖拽和拖動,... ...
  • 1、Blazor Hybrid簡介 Blazor Hybrid 使開發人員能夠將桌面和移動本機客戶端框架與 .NET 和 Blazor 結合使用。在 Blazor Hybrid 應用中,Razor 組件在設備上是本機運行的。 這些組件通過本地互操作通道呈現到嵌入式 Web 視圖控制項。 組件不在瀏覽器 ...
  • 除了內置的數據集,scikit-learn還提供了隨機樣本的生成器。通過這些生成器函數,可以生成具有特定特性和分佈的隨機數據集,以幫助進行機器學習演算法的研究、測試和比較。 目前,scikit-learn庫(v1.3.0版)中有20個不同的生成樣本的函數。本篇重點介紹其中幾個具有代表性的函數。 1. ...
  • 從0到1,手把手帶你開發截圖工具ScreenCap------002實現通過文件對話框,選擇合適的文件夾,自定義預設的圖片保存位置,簡單易學 ...
  • 每次談到容器的時候,除了Docker之外,都會說起 Kubernetes,那麼什麼是 Kubernetes呢?今天就來一起學快速入門一下 Kubernetes 吧!希望本文對您有所幫助。 Kubernetes,一種用於管理和自動化雲中容器化工作負載的工具。 想象一下你有一個管弦樂隊,將每個音樂家視為 ...
  • 目錄 基本說明 安裝 Nginx 部署 VUE 前端 部署 Django 後端 Django admin 靜態文件(CSS,JS等)丟失的問題 總結 1. 基本說明 本文介紹了在 windows 伺服器下,通過 Nginx 部署 VUE + Django 前後端分離項目。本項目前端運行在 80 埠 ...
  • 從0到1,手把手帶你開發截圖工具ScreenCap------003實現最小化程式到托盤運行,- 為了方便截圖乾凈,實現最小化程式到托盤運行,簡潔,勿擾,實現最小化程式到托盤運行, 實現托盤菜單功能,實現回顯主窗體, 實現托盤開始截屏, 實現氣泡信息提示,實現托盤程式提示,實現托盤退出程式, 封裝完... ...