網站搜尋

如何覆寫通過 @types/package 安裝的錯誤 TypeScript 類型定義


假設我想在我的 TypeScript 專案中使用 dotenv 模組,並用 npm install @types/dotenv --save 安裝它的 .d.ts。然後我發現類型定義不正確。例如,config() 函數返回的不是布林值,而是一個更豐富的物件。

我該如何處理這種情況?我是否應該把下載的類型定義複製到另一個檔案,手動更新它,然後卸載 @types/dotenv?有更好的方法嗎?(我需要立即修復,而不是等到上游維護者合併之後。)

答案#1

你可以使用 patch-package 在本地為你的應用程式修補 @types/foo。

  1. 執行 npm i -D patch-package

  2. 只需修改 node_modules/@types/foo 以符合您的需求。

  3. 運行 npx patch-package @types/foo。這會在 patches/ 中創建一個 diff 文件,用來記錄從上一步所做的更改。

  4. 在 package.json 中添加 "scripts": {"postinstall": "patch-package"}。這樣每次人們運行 npm install 時,補丁都會被應用。

答案#2

這裡沒有提到的一種方法是將類型聲明放在 index.d.ts 文件中。就我而言,@types/react-bootstrap 的類型是不正確的。

我想使用文檔中聲明的 bsClass,但在 Popover 中不存在。相反,他們包含了一個在 Popover 上不存在的屬性,即 bsStyle。

對我來說的解決方法是移除 bsStyle 並添加 bsClass:

import * as React from "react";
import { Sizes } from "react-bootstrap";

// Overwrite bad declaration from @types/react-bootstrap
declare module "react-bootstrap" {
    namespace Popover {
        export interface PopoverProps extends React.HTMLProps<Popover> {
            // Optional
            arrowOffsetLeft?: number | string;
            arrowOffsetTop?: number | string;
            bsSize?: Sizes;
            bsClass?: string; // This is not included in types from @types/react-bootstrap
            placement?: string;
            positionLeft?: number | string;
            positionTop?: number | string;
        }
    }
    class Popover extends React.Component<Popover.PopoverProps> { }
}

更新

我終於鼓起勇氣,上傳了一個 PR 到 DefinitelyTyped,以添加一些缺失的 bsClass/bsSize 宣告。

更新 2:使用宣告合併的範例

我想在 React 中為 <img> 標籤添加 loading="lazy" 屬性,但它還沒有合併。我是這樣解決的:

檔案:global.d.ts

// Unused import - only used to make this file a module (otherwise declare global won't work)
// tslint:disable-next-line:no-unused
import React from "react";

// Extend HTMLImageElement to support image lazy loading
// https://addyosmani.com/blog/lazy-loading/
declare global {
    namespace React {
        interface ImgHTMLAttributes<T> {
            loading?: "lazy" | "eager" | "auto";
        }
    }
}

答案#3

我會從 DefinitelyTyped 複製宣告檔案,在本地修改它們,向 DefinitelyTyped 提交 PR,然後按照以下問題中給出的建議立即使用這些更改:我如何編寫並使用 DefinitelyTyped 上不存在的自訂宣告檔案?

將更新傳送到 DefinitelyTyped

  1. 前往 DefinitelyTyped 倉庫:https://github.com/DefinitelyTyped/DefinitelyTyped/
  2. 在本地克隆你的分支。(通常只需 git clone https://github.com/YourUserName/DefinitelyTyped/)
  3. 為你的更新建立一個分支(例如 git branch changes-to-xyz)
  4. 對你感興趣的套件進行修改。
  5. 新增並提交檔案。(git add types; git commit)
  6. 然後將它們推送到你自己的 DefinitelyTyped 分支(git push -u origin changes-to-xyz)

在本地使用那些更新

  1. 在你的專案中建立一個 local-types 資料夾。
  2. 將你修改過的 DefinitelyTyped 資料夾(我們稱它為 xyz)複製到 local-types/xyz。
  3. 從 local-types/xyz 執行 npm init --scope types --yes。
  4. 從你的專案根目錄,執行 npm install local-types/xyz

就這樣!

答案#4

我會檢查 dotenv 的版本和 @types/dotenv 的版本是否一致,這可能是導致函數缺失的原因。

如果是的話,更乾淨的方法就是自己修改 .d.ts。

為了做到這一點:npm remove @types/dotenv。在你的專案中建立一個資料夾 types。將 node_modules/@types 中找到的整個 資料夾 dotenv 複製到其中。

然後修正其中的 d.ts 並修改你的 tsconfig.json,告訴它也去你新的資料夾中尋找缺失的類型,使用 typeRoots 如下所示:

{
"compilerOptions": {
    "module": "commonjs",
    "noImplicitAny": true,
    "typeRoots": [
        "./node_modules/@types",
        "./types/",
    ]
},
"files": ["./app.ts"]
}

(別忘了加入 ./node_modules/@types 或其他你透過 npm 獲得、現在找不到的類型。)