typescript - ไม่สามารถประกาศตัวแปรแบบมีขอบเขตบล็อกซ้ำได้
ฉันกำลังสร้างแอป Node และภายในแต่ละไฟล์ใน .js มักจะทำแบบนี้เพื่อเรียกใช้แพ็กเกจต่างๆ
let co = require("co");
แต่การได้รับ
เป็นต้น ดังนั้นการใช้ TypeScript ดูเหมือนว่าจะสามารถมีการประกาศ/การเรียกใช้เพียงครั้งเดียวในโครงการทั้งหมด? ฉันสับสนเกี่ยวกับเรื่องนี้เพราะฉันคิดว่า let ถูกจำกัดขอบเขตอยู่ที่ไฟล์ปัจจุบัน
ฉันเพิ่งมีโปรเจกต์ที่ใช้งานได้ แต่หลังจากการปรับโครงสร้างโค้ด ตอนนี้ฉันได้รับข้อผิดพลาดเหล่านี้เต็มไปหมด
มีใครอธิบายได้ไหม?
คำตอบ #1
คำอธิบายที่ดีที่สุดที่ฉันได้รับมาคือจากโพสต์ของ Tamas Piro
สรุปสั้น ๆ; TypeScript ใช้การกำหนดประเภท DOM สำหรับสภาพแวดล้อมการทำงานแบบทั่วโลก ในกรณีของคุณมีคุณสมบัติ 'co' บนวัตถุ window ทั่วโลก
เพื่อแก้ไขเรื่องนี้:
เปลี่ยนชื่อค่าตัวแปร หรือ
ใช้โมดูล TypeScript และเพิ่ม export{} ว่าง:
export {};หรือ
กำหนดค่าตัวเลือกคอมไพเลอร์ของคุณโดยไม่เพิ่มการพิมพ์ 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
แน่นอนว่ายังมีรายละเอียดอื่นอีกมากกว่านี้ แต่สำหรับการเริ่มต้น:
แทนที่อินสแตนซ์ของ
requireด้วยimportเช่นแทนที่ :
const https = require('https');ด้วย :
import https from 'https';แทนที่
module.exportsเริ่มต้นด้วยexport defaultเช่นแทนที่ :
module.exports = myVar ...ด้วย :
export default myVar ...แทนที่
module.exportsอื่นๆ ด้วยexportเช่นแทนที่ :
module.exports.myVar =หรือ :
module.export = { myVar ... }ด้วย :
export myVar ...
เพิ่มเติมที่นี่: จาก CommonJS ไปยัง ES Modules: วิธีปรับปรุงแอป Node.js ของคุณให้ทันสมัย
