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


99

ฉันกำลังสร้างแอปโหนดและภายในแต่ละไฟล์ใน. js เคยทำสิ่งนี้เพื่อต้องการในแพ็คเกจต่างๆ

let co = require("co");

แต่ได้รับ

ป้อนคำอธิบายภาพที่นี่

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

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

ใครช่วยอธิบายหน่อย


1
วิธีนี้ - ให้ co_module = ต้องใช้ ("co"); ฉันเผชิญกับสิ่งที่คล้ายกันและสิ่งนี้แก้ไขข้อผิดพลาดได้
tyrion

1
นี่น่าจะเป็นข้อบกพร่องของตัวพิมพ์ ฉันได้ทำตัวอย่างขั้นต่ำที่นี่: gist.github.com/rjmunro/428ec644b6e53a499ca3a5ba8de2edc7
rjmunro

5
2.5 ปีต่อมาและฉันกลับมาที่คำถามของตัวเองนี่ยังคงเป็นปัญหา คราวนี้มีโหนดในตัว const fs = require('fs')ให้ข้อผิดพลาดที่คล้ายกันดังนั้นไม่แน่ใจว่าจะนำเข้าจากห้องสมุดใด ...
dcsan

ความจริงที่ TS ยังคงทำสิ่งนี้ไร้สาระ
GN

คำตอบ:


67

เกี่ยวกับข้อผิดพลาดนั้น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;

หากคุณได้รับข้อผิดพลาด"ไม่พบโมดูลร่วม" ...

TypeScript กำลังเรียกใช้การตรวจสอบประเภทเต็มรูปแบบกับโมดูลดังนั้นหากคุณไม่มีข้อกำหนด TS สำหรับโมดูลที่คุณพยายามนำเข้า (เช่นเนื่องจากเป็นโมดูล JS ที่ไม่มีไฟล์ข้อกำหนด) คุณสามารถประกาศโมดูลของคุณใน.d.tsไฟล์ข้อกำหนดที่ไม่ ไม่มีการส่งออกระดับโมดูล:

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

9
สิ่งนี้ทำให้ "ไม่พบโมดูลร่วม" ฉันยังพยายามที่จะให้typings install co Unable to find "co" in the registryความคิดอื่น ๆ ?
dcsan

ฉันมีปัญหาเดียวกันกับ @dcsan มันบอกว่าไม่พบโมดูลแม้ว่าฉันจะติดตั้ง npm แล้วก็ตาม
justin.m.chase

อาจเกิดจากเส้นทางสัมพัทธ์ ฉันไม่คุ้นเคยกับการจัดการโมดูล NodeJS แต่ใน RequireJS หากมีการอ้างอิงถึงโมดูลค่อนข้างมากโฟลเดอร์ปัจจุบันจะต้องแสดงอย่างชัดเจน นั่นคือ./coแทนที่จะเป็นcoถ้า co.ts อยู่ในโฟลเดอร์เดียวกัน (หรือเอาต์พุตที่คอมไพล์ co.js)
John Weisz

1
เอาใจใส่ "* เป็น xxx" เป็นสิ่งสำคัญ ดังนั้นไม่ใช่ "นำเข้า xxx จาก ... " แต่เป็น "นำเข้า * เป็น xxx จาก ... "
Nurbol Alpysbayev

27

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

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

วิธีแก้ปัญหานี้:

  1. เปลี่ยนชื่อตัวแปรหรือ
  2. ใช้โมดูล TypeScript และเพิ่มการส่งออกที่ว่างเปล่า {}:
export {};

หรือ

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

แก้ไข tsconfig.json ในไดเร็กทอรีโปรเจ็กต์ TypeScript

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

สำหรับฝั่งไคลเอ็นต์? ปัญหาเดิมของฉันคือรหัสฝั่งเซิร์ฟเวอร์และฉันไม่เชื่อว่ามีการใช้ตัวเลือกคอมไพเลอร์ DOM (โครงการเก่า)
dcsan

1
ฉันยืนยันว่าการเพิ่มexport {}ช่วยแก้ปัญหาให้ฉันได้ แต่การเพิ่ม"compilerOptions": { "lib": ["es6"] }ดูเหมือนจะไม่ช่วยอะไรทั้งในระหว่างการรวบรวมทั้งใน VSCode
adamsfamily

ลิงก์ไปยังโพสต์ต้นฉบับตายแล้ว
Cyclonecode

13

ฉันได้รับข้อผิดพลาดที่คล้ายกันนี้เมื่อรวบรวมแอปพลิเคชัน 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"]
}

9

การใช้งานIIFE(Immediately Invoked Function Expression), IIFE

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

 })();

เรียบง่าย ทำงานได้อย่างสมบูรณ์ ขอบคุณ! (ในกรณีของฉันฉันกำลังประกาศว่าconst expect = chai.expect;จะใช้การทดสอบแตงกวาในโครงการ Angular 5)
Maxime Lafarie

7

สำหรับผู้ที่มาที่นี่ในยุคนี้นี่เป็นวิธีง่ายๆสำหรับปัญหานี้ อย่างน้อยมันก็ได้ผลสำหรับฉันในแบ็กเอนด์ ฉันยังไม่ได้ตรวจสอบด้วยรหัสส่วนหน้า

เพียงเพิ่ม:

export {};

ที่ด้านบนสุดของรหัสของคุณ

ให้เครดิตกับEUGENE MURAVITSKY


1

ฉันพบปัญหาเดียวกันและวิธีแก้ปัญหาของฉันมีลักษณะดังนี้:

// *./module1/module1.ts*
export module Module1 {
    export class Module1{
        greating(){ return 'hey from Module1'}
    }
}


// *./module2/module2.ts*
import {Module1} from './../module1/module1';

export module Module2{
    export class Module2{
        greating(){
            let m1 = new Module1.Module1()
            return 'hey from Module2 + and from loaded Model1: '+ m1.greating();
        }
    }
}

ตอนนี้เราสามารถใช้งานได้ที่ฝั่งเซิร์ฟเวอร์:

// *./server.ts*
/// <reference path="./typings/node/node.d.ts"/>
import {Module2} from './module2/module2';

export module Server {
    export class Server{
        greating(){
            let m2 = new Module2.Module2();
            return "hello from server & loaded modules: " + m2.greating();
        }
    }
}

exports.Server = Server;

// ./app.js
var Server = require('./server').Server.Server;
var server = new Server();
console.log(server.greating());

และในฝั่งลูกค้าด้วย:

// *./public/javscripts/index/index.ts*

import {Module2} from './../../../module2/module2';

document.body.onload = function(){
    let m2 = new Module2.Module2();
    alert(m2.greating());
}

// ./views/index.jade
extends layout

block content
  h1= title
  p Welcome to #{title}
  script(src='main.js')
  //
    the main.js-file created by gulp-task 'browserify' below in the gulpfile.js

และแน่นอนไฟล์อึกสำหรับทั้งหมดนี้:

// *./gulpfile.js*
var gulp = require('gulp'),
    ts = require('gulp-typescript'),
    runSequence = require('run-sequence'),
    browserify = require('gulp-browserify'),
    rename = require('gulp-rename');

gulp.task('default', function(callback) {

    gulp.task('ts1', function() {
        return gulp.src(['./module1/module1.ts'])
            .pipe(ts())
            .pipe(gulp.dest('./module1'))
    });

    gulp.task('ts2', function() {
        return gulp.src(['./module2/module2.ts'])
            .pipe(ts())
            .pipe(gulp.dest('./module2'))
    });

    gulp.task('ts3', function() {
        return gulp.src(['./public/javascripts/index/index.ts'])
            .pipe(ts())
            .pipe(gulp.dest('./public/javascripts/index'))
    });

    gulp.task('browserify', function() {
        return gulp.src('./public/javascripts/index/index.js', { read: false })
            .pipe(browserify({
                insertGlobals: true
            }))
            .pipe(rename('main.js'))
            .pipe(gulp.dest('./public/javascripts/'))
    });

    runSequence('ts1', 'ts2', 'ts3', 'browserify', callback);
})

อัปเดตแล้ว แน่นอนว่าไม่จำเป็นต้องรวบรวมไฟล์ typescript แยกจากกัน runSequence(['ts1', 'ts2', 'ts3'], 'browserify', callback)ทำงานได้อย่างสมบูรณ์แบบ


7
ในกรณีที่ใครก็ตามถูกถอด TypeScript ด้วยความละเอียดและความซ้ำซากของไฟล์อึกนั้นก็ไม่มีใครทำเช่นนี้
Daniel Earwicker

0

ฉันได้รับข้อผิดพลาดนี้เมื่ออัปเกรด

gulp-typescript 3.0.2 → 3.1.0

การใส่กลับไปที่ 3.0.2 ได้รับการแก้ไขแล้ว


0

ในกรณีของฉันtsconfig.jsonปัญหาที่แก้ไขได้ต่อไปนี้:

{
  "compilerOptions": {
    "esModuleInterop": true,
    "target": "ES2020",
    "moduleResolution": "node"
  }
}

ไม่ควรมีtype: moduleในpackage.json.

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.