ค้นหาเว็บไซต์

typescript - ไม่สามารถประกาศตัวแปรแบบมีขอบเขตบล็อกซ้ำได้


ฉันกำลังสร้างแอป Node และภายในแต่ละไฟล์ใน .js มักจะทำแบบนี้เพื่อเรียกใช้แพ็กเกจต่างๆ

let co = require("co");

แต่การได้รับ

เป็นต้น ดังนั้นการใช้ TypeScript ดูเหมือนว่าจะสามารถมีการประกาศ/การเรียกใช้เพียงครั้งเดียวในโครงการทั้งหมด? ฉันสับสนเกี่ยวกับเรื่องนี้เพราะฉันคิดว่า let ถูกจำกัดขอบเขตอยู่ที่ไฟล์ปัจจุบัน

ฉันเพิ่งมีโปรเจกต์ที่ใช้งานได้ แต่หลังจากการปรับโครงสร้างโค้ด ตอนนี้ฉันได้รับข้อผิดพลาดเหล่านี้เต็มไปหมด

มีใครอธิบายได้ไหม?

คำตอบ #1

คำอธิบายที่ดีที่สุดที่ฉันได้รับมาคือจากโพสต์ของ Tamas Piro

สรุปสั้น ๆ; TypeScript ใช้การกำหนดประเภท DOM สำหรับสภาพแวดล้อมการทำงานแบบทั่วโลก ในกรณีของคุณมีคุณสมบัติ 'co' บนวัตถุ window ทั่วโลก

เพื่อแก้ไขเรื่องนี้:

  1. เปลี่ยนชื่อค่าตัวแปร หรือ

  2. ใช้โมดูล TypeScript และเพิ่ม export{} ว่าง:

    export {};
    

    หรือ

  3. กำหนดค่าตัวเลือกคอมไพเลอร์ของคุณโดยไม่เพิ่มการพิมพ์ DOM:

แก้ไข tsconfig.json ในไดเรกทอรีโครงการ TypeScript

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

คำตอบ #2

เกี่ยวกับข้อผิดพลาดเอง, let ถูกใช้เพื่อประกาศตัวแปร ท้องถิ่น ที่อยู่ในขอบเขตบล็อกแทนขอบเขตฟังก์ชัน นอกจากนี้มันยังเข้มงวดกว่า var ดังนั้นคุณไม่สามารถทำสิ่งต่าง ๆ แบบนี้ได้:

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

โปรดสังเกตด้วยว่า case ภายในบล็อก switch จะไม่สร้างขอบเขตบล็อกของตัวเอง ดังนั้นคุณจึงไม่สามารถประกาศตัวแปรท้องถิ่นซ้ำในหลาย 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 {};

ที่ด้านบนของไฟล์ใด ๆ ที่มีโค้ดโดยไม่มีการส่งออกที่มีอยู่

เครดิตให้กับ ยูจีน มูราวิทสกี้

คำตอบ #4

ฉันก็เคยเจอปัญหานี้ตอนทำงานกับ ts บน vscode วิธีที่ฉันแก้ไขมันง่าย แต่ก็อาจจะไม่เหมือนกับปัญหาของคุณ

ตัวแก้ไขของฉันแสดงข้อผิดพลาดนี้เมื่อฉันเปิดไฟล์ TypeScript และไฟล์ JavaScript พร้อมกันในแท็บล่าสุด ฉันก็แค่ปิดมันและข้อผิดพลาดก็หายไป

หวังว่าสิ่งนี้จะช่วยใครบางคนที่อาจกำลังเกาหัวกับบั๊กง่าย ๆ นี้อยู่เช่นกัน

คำตอบ #5

นี่ถูกแก้ไขผ่าน "moduleDetection": "force" ใน tsconfig.json ของคุณ:

{
  "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 Modules (import, export, ฯลฯ)

เอกสาร TypeScript ยังดูเหมือนจะแนะนำไวยากรณ์ ES Module ด้วย: โมดูล 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 Modules: วิธีปรับปรุงแอป Node.js ของคุณให้ทันสมัย

บทความที่เกี่ยวข้อง