如何覆寫通過 @types/package 安裝的錯誤 TypeScript 類型定義
假設我想在我的 TypeScript 專案中使用 dotenv 模組,並用 npm install @types/dotenv --save 安裝它的 .d.ts。然後我發現類型定義不正確。例如,config() 函數返回的不是布林值,而是一個更豐富的物件。
我該如何處理這種情況?我是否應該把下載的類型定義複製到另一個檔案,手動更新它,然後卸載 @types/dotenv?有更好的方法嗎?(我需要立即修復,而不是等到上游維護者合併之後。)
答案#1
你可以使用 patch-package 在本地為你的應用程式修補 @types/foo。
執行
npm i -D patch-package只需修改
node_modules/@types/foo以符合您的需求。運行
npx patch-package @types/foo。這會在patches/中創建一個 diff 文件,用來記錄從上一步所做的更改。在
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
- 前往 DefinitelyTyped 倉庫:https://github.com/DefinitelyTyped/DefinitelyTyped/
- 在本地克隆你的分支。(通常只需
git clone https://github.com/YourUserName/DefinitelyTyped/) - 為你的更新建立一個分支(例如
git branch changes-to-xyz) - 對你感興趣的套件進行修改。
- 新增並提交檔案。(
git add types; git commit) - 然後將它們推送到你自己的 DefinitelyTyped 分支(
git push -u origin changes-to-xyz)
在本地使用那些更新
- 在你的專案中建立一個
local-types資料夾。 - 將你修改過的 DefinitelyTyped 資料夾(我們稱它為
xyz)複製到local-types/xyz。 - 從
local-types/xyz執行npm init --scope types --yes。 - 從你的專案根目錄,執行
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 獲得、現在找不到的類型。)
