如何手動補充陳年老庫(或純 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
  • Dapr Outbox 是1.12中的功能。 本文只介紹Dapr Outbox 執行流程,Dapr Outbox基本用法請閱讀官方文檔 。本文中appID=order-processor,topic=orders 本文前提知識:熟悉Dapr狀態管理、Dapr發佈訂閱和Outbox 模式。 Outbo ...
  • 引言 在前幾章我們深度講解了單元測試和集成測試的基礎知識,這一章我們來講解一下代碼覆蓋率,代碼覆蓋率是單元測試運行的度量值,覆蓋率通常以百分比表示,用於衡量代碼被測試覆蓋的程度,幫助開發人員評估測試用例的質量和代碼的健壯性。常見的覆蓋率包括語句覆蓋率(Line Coverage)、分支覆蓋率(Bra ...
  • 前言 本文介紹瞭如何使用S7.NET庫實現對西門子PLC DB塊數據的讀寫,記錄了使用電腦模擬,模擬PLC,自至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1.Windows環境下鏈路層網路訪問的行業標準工具(WinPcap_4_1_3.exe)下載鏈接:http ...
  • 從依賴倒置原則(Dependency Inversion Principle, DIP)到控制反轉(Inversion of Control, IoC)再到依賴註入(Dependency Injection, DI)的演進過程,我們可以理解為一種逐步抽象和解耦的設計思想。這種思想在C#等面向對象的編 ...
  • 關於Python中的私有屬性和私有方法 Python對於類的成員沒有嚴格的訪問控制限制,這與其他面相對對象語言有區別。關於私有屬性和私有方法,有如下要點: 1、通常我們約定,兩個下劃線開頭的屬性是私有的(private)。其他為公共的(public); 2、類內部可以訪問私有屬性(方法); 3、類外 ...
  • C++ 訪問說明符 訪問說明符是 C++ 中控制類成員(屬性和方法)可訪問性的關鍵字。它們用於封裝類數據並保護其免受意外修改或濫用。 三種訪問說明符: public:允許從類外部的任何地方訪問成員。 private:僅允許在類內部訪問成員。 protected:允許在類內部及其派生類中訪問成員。 示 ...
  • 寫這個隨筆說一下C++的static_cast和dynamic_cast用在子類與父類的指針轉換時的一些事宜。首先,【static_cast,dynamic_cast】【父類指針,子類指針】,兩兩一組,共有4種組合:用 static_cast 父類轉子類、用 static_cast 子類轉父類、使用 ...
  • /******************************************************************************************************** * * * 設計雙向鏈表的介面 * * * * Copyright (c) 2023-2 ...
  • 相信接觸過spring做開發的小伙伴們一定使用過@ComponentScan註解 @ComponentScan("com.wangm.lifecycle") public class AppConfig { } @ComponentScan指定basePackage,將包下的類按照一定規則註冊成Be ...
  • 操作系統 :CentOS 7.6_x64 opensips版本: 2.4.9 python版本:2.7.5 python作為腳本語言,使用起來很方便,查了下opensips的文檔,支持使用python腳本寫邏輯代碼。今天整理下CentOS7環境下opensips2.4.9的python模塊筆記及使用 ...