網站搜尋

TypeScript - 無法重新宣告區塊範圍變數


我正在建立一個 Node 應用程式,在每個 .js 檔案中通常都是這樣做來引入各種套件。

let co = require("co");

但得到

等等。所以使用 TypeScript 似乎整個專案中只能有一個這樣的聲明/require?我對此感到困惑,因為我以為 let 的作用域是當前文件。

我剛有一個正在運作的專案,但在重構之後,現在到處都出現這些錯誤。

有人可以解釋嗎?

答案#1

我能得到的最佳解釋來自Tamas Piro的帖子。

TLDR;TypeScript 使用 DOM 型別定義來描述全域執行環境。在你的情況下,global window 物件上有一個 'co' 屬性。

要解決這個問題:

  1. 重新命名變數,或者

  2. 使用 TypeScript 模組,並添加一個空的 export{}:

    export {};
    

    或

  3. 透過不添加 DOM 型別來配置你的編譯器選項:

編輯 TypeScript 專案目錄中的 tsconfig.json。

{
    "compilerOptions": {
        "lib": ["es6"]
      }
}

答案#2

關於錯誤本身,let 用來宣告存在於區塊範圍而非函式範圍的區域變數。它也比 var 更嚴格,所以你不能這樣做:

if (condition) {
    let a = 1;
    ...
    let a = 2;
}

另請注意,switch 區塊中的 case 子句不會創建自己的區塊範圍,因此如果不使用 {} 來創建區塊,你不能在多個 case 中重新宣告相同的區域變數。

至於匯入,你可能會遇到這個錯誤,是因為 TypeScript 並未將你的檔案識別為真正的模組,而看似的模型層級定義最終對它來說變成了全域定義。

嘗試以標準的 ES6 方式導入外部模組,該模組不包含明確的賦值,應該能讓 TypeScript 正確識別你的檔案為模組:

import * as co from "./co"

如果你已經有一個名為 co 的東西,這仍然會導致編譯錯誤,這是預期中的。例如,這將會是錯誤:

import * as co from "./co"; // Error: import definition conflicts with local definition
let co = 1;

如果你收到錯誤 「找不到模組 co」...

TypeScript 正在對模組進行完整的類型檢查,因此如果你沒有要導入的模組的 TS 定義(例如,因為它是沒有定義文件的 JS 模組),你可以在不包含模組層級導出的 .d.ts 定義文件中 聲明 你的模組:

declare module "co" {
    declare var co: any;
    export = co;
}

答案#3

對於在這個時代來到這裡的人,這裡有一個對這個問題的簡單解決方案。至少對我在後端有用。我還沒有檢查前端代碼。

只要加上:

export {};

在任何沒有現有匯出的程式碼檔案頂部。

致謝 EUGENE MURAVITSKY

答案#4

我在使用 VSCode 處理 ts 時也遇到過這個問題。我解決這個問題的方法很簡單,但可能與你的問題不一樣。

當我在最近的標籤中同時打開 TypeScript 文件和 JavaScript 文件時,我的編輯器會顯示此錯誤。我只需關閉它,錯誤就會消失。

希望這能幫助到可能也因這個簡單的錯誤而抓頭的人。

答案#5

這可以透過在你的 tsconfig.json 中使用 "moduleDetection": "force" 來解決:

{
  "compilerOptions": {
    "moduleDetection": "force"
  }
}   

參考資料:https://www.typescriptlang.org/tsconfig#moduleDetection

原始答案: https://stackoverflow.com/a/74968079/10538886

答案#6

我在編譯我的 Node.JS Typescript 應用程式時收到了類似的錯誤:

node_modules/@types/node/index.d.ts:83:15 - error TS2451: Cannot redeclare block-scoped variable 'custom'.

解決方法是移除這個:

"files": [
  "./node_modules/@types/node/index.d.ts"
]

並用這個取代它:

"compilerOptions": {
  "types": ["node"]
}

答案#7

使用 IIFE(立即呼叫函式表達式),IIFE

(function () {
    all your code is here...

 })();

答案#8

對我來說的解決方案是將我的程式碼從使用 CommonJS(require、module.exports 等)轉換為 ES 模組(import、export 等)。

TypeScript 文件也似乎建議使用 ES 模組語法:TypeScript 模組

當然,這其中還有很多內容,不過作為起點:

  1. 將 require 的用法替換為 import,例如。

    替換:

    const https = require('https');
    

    與:

    import https from 'https';
    
  2. 將預設的 module.exports 替換為 export default,例如。

    替換:

    module.exports = myVar ...
    

    與:

    export default myVar ...
    
  3. 將其他 module.exports 替換為 export,例如。

    替換:

    module.exports.myVar = 
    

    或 :

    module.export = { myVar ... }
    

    與:

    export myVar ...
    

更多內容:從 CommonJS 到 ES 模組:如何現代化你的 Node.js 應用程式