網站搜尋

Koa + TypeScript:屬性 'body' 在類型 Request 上不存在


我想要在 TypeScript 中使用 koa 和 koa-bodyparser,但每次我訪問 ctx.request.body 時,都會出現錯誤,提示 body 在類型 Request 上不存在

import Koa from 'koa'
import Router from 'koa-router'
import bodyparser from 'koa-bodyparser'

const app = new Koa()
const router = new Router()

const data = ['lorem', 'ipsum', 'dolor', 'sit', 'amet']

app.use(bodyparser())
router.post('/', (ctx, next) => {
  const phrase = ctx.request.body; // Property 'body' does not exist on type Request
  if (typeof phrase === 'string') {
    ctx.response.body = data.filter(element => element.includes(phrase))
  }
})

答案#1

在終端機執行 npm install --save-dev @types/koa-bodyparser,且在你package.json所在的目錄中

此套件包含由 koa-bodyparser 引入的類型(例如 request.body)

答案#2

如果你是從未來來的,還有一個可能導致此問題的額外情況。情景:

  1. 過去的你:安裝 koa、koa-bodyparser、@types/koa、@types/koa-bodyparser
  2. 代碼:一切運作良好
  3. 今天你:該升級了;更新[所有那些套件]
  4. 代碼:屬性 'body' 不存在於類型 Request 上

TL;DR: yarn.lock,所以執行 yarn dedupe @types/koa。


發生了什麼事?

更深入地查看,在你的 node_modules 中,你會看到:

- node_modules/
  - @types/koa/
  - @types/koa-bodyparser/
      - node_modules/
      -   @types/koa/

那為什麼重要?

讓我們來看看 @koa-bodyparser 來了解一下。以下是相關的程式碼行,以及它的工作原理:

import * as Koa from "koa";

declare module "koa" {
    interface Request {
        body?: any;
        rawBody: string;
    }
}

它所做的是為你正在使用的 koa 套件中的 Request 類型定義額外的參數,對吧?嗯,通常是這樣,但不完全是。它還依賴於 @types/koa,因為在文件開頭有 import。它實際上所做的是為它使用的 koa 對象中的 Request 類型定義額外的參數,並且由於它現在使用的版本跟你不同,你就不再擁有那個好處了。

那麼,為什麼會發生這種事呢?

當你第一次安裝所有東西時,yarn 建立了一個依賴樹,查看每個 package.json 中的版本,最終得到這個結果:

"@types/koa@*", "@types/koa@^2.13.1":
  version "2.13.1"
  ... resolved, integrity, dependencies, etc.

@types/koa@^2.13.1 將是你在 package.json 中安裝的任何版本。@types/koa@* 是 @types/koa-bodyparser 中的版本。

然後當你更新時,yarn 會建立一個依賴樹,檢查每個 package.json 中的版本,並將其與已存在的版本進行比較。你的程式碼現在寫著 @types/koa@^2.13.5,因此 yarn 需要為它安裝一個新版本。@types/bodyparser 仍然寫著 @types/koa@*,這在 yarn.lock 中已經被考慮到,因此你最終會得到一個看起來像這樣的 yarn.lock:

"@types/koa@*":
  version "2.13.1"
  ... resolved, integrity, dependencies, etc.

"@types/koa@^2.13.5":
  version "2.13.5"
  ... resolved, integrity, dependencies, etc.

現在由於你沒有使用相同的版本,一個會安裝在你的 node_modules 中,而另一個會安裝在請求它的套件的 node_modules 中。

那我該怎麼修復它?

更新至2024

你只需要對那個套件去重。執行這個以告訴 yarn 更新所有非破壞性範圍內的內容(結果與「先前答案」相同,無需手動修改鎖定檔)。

yarn dedupe @types/koa

如果你想看看未來可能會遇到哪些其他問題,你可以運行此命令來檢查(乾跑)所有的套件。請記住:擁有不必要的副本意味著開發人員的安裝時間更長以及部署時間更長。

yarn dedupe --check

然後,如果你喜歡它,你可以選擇運行

  1. yarn dedupe

    • 根據文件,這將確保當版本重疊時,你擁有的套件副本數量最少,如果某個程式庫需要較低版本的套件,這可能會降級其中一些套件。
    • 因為它必須先尋找版本重疊,所以速度會稍微慢一些,但最終產生的檔案較少。
  2. yarn dedupe --strategy highest

    • 根據文件,這將確保套件總是使用它們支援的最新版本,就好像你是全新安裝一樣。如果有一個套件需要較低的版本而其他套件不需要,你最終會有多個副本,但不受限制的程式碼將使用它支援的最新版本。
    • 因為它只是使用最高支持的,所以速度較快(可以一次完成),但經常會導致重複。
    • 對於當前的問題,嵌套的套件需要 *。如果你的程式碼需要比 latest 低整個主要版本,它可能無法解決這個問題。這種情況比較罕見,但如果你已經走到這裡,你可能想要記住這是可能的。

註解 1:請記住,並非所有套件都遵循語義化版本控制(semver),因此你在一次性對所有套件進行這種操作時仍需小心,最好先使用 --check 並確認你對這些變更沒有問題。

注意 2:如果你正在使用 Yarn 1,dedupe 尚未內建,所以我建議安裝 yarn-deduplicate,然後運行 yarn-deduplicate --packages @types/koa。

先前的答案

最簡單的方法?刪除你 yarn.lock 文件中整個 @types/koa@* 區塊,然後再次運行 yarn。你現在將得到這個結果:

"@types/koa@*", "@types/koa@^2.13.5":
  version "2.13.5"
  ... resolved, integrity, dependencies, etc.

一切又再次幸福,直到下次。