tidak dapat mendeklarasikan ulang blok variabel cakupan (skrip jenis)

99

Saya sedang membangun aplikasi node, dan di dalam setiap file dalam .js dulu melakukan ini untuk meminta dalam berbagai paket.

let co = require("co");

Tapi mendapatkan

masukkan deskripsi gambar di sini

dll. Jadi dengan menggunakan skrip jenis sepertinya hanya ada satu deklarasi / kebutuhan seperti itu di seluruh proyek? Saya bingung tentang ini karena saya pikir letitu cakupan ke file saat ini.

Saya baru saja memiliki proyek yang berfungsi tetapi setelah refactor sekarang saya mendapatkan kesalahan ini di semua tempat.

Ada yang bisa menjelaskan?

dcsan.dll
sumber
1
Bagaimana dengan ini - misalkan co_module = require ("co"); Saya menghadapi hal serupa dan ini menyelesaikan kesalahan.
tyrion
1
Ini sepertinya bug ketikan. Saya telah membuat contoh minimal di sini: gist.github.com/rjmunro/428ec644b6e53a499ca3a5ba8de2edc7
rjmunro
5
2,5 tahun kemudian dan saya kembali pada pertanyaan saya sendiri, ini masih menjadi masalah. kali ini dengan node built in. const fs = require('fs')memberikan kesalahan serupa jadi tidak yakin perpustakaan mana yang akan mengimpor ini dari ...
dcsan
Fakta TS masih melakukan ini konyol
GN.

Jawaban:

67

Mengenai kesalahan itu sendiri, letdigunakan untuk mendeklarasikan variabel lokal yang ada dalam cakupan blok, bukan cakupan fungsi. Ini juga lebih ketat dari var, jadi Anda tidak bisa melakukan hal-hal seperti ini:

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

Perhatikan juga bahwa caseklausa di dalam switchblok tidak membuat cakupan bloknya sendiri, jadi Anda tidak dapat mendeklarasikan ulang variabel lokal yang sama di beberapa blok casetanpa menggunakan {}masing-masing untuk membuat blok.


Adapun impor, Anda mungkin mendapatkan kesalahan ini karena TypeScript tidak mengenali file Anda sebagai modul yang sebenarnya, dan tampaknya definisi tingkat model akhirnya menjadi definisi global untuk itu.

Coba impor modul eksternal dengan cara ES6 standar , yang tidak berisi penetapan eksplisit, dan harus membuat TypeScript mengenali file Anda dengan benar sebagai modul:

import * as co from "./co"

Ini masih akan menghasilkan kesalahan kompilasi jika Anda memiliki sesuatu yang cosudah dinamai , seperti yang diharapkan. Misalnya, ini akan menjadi kesalahan:

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

Jika Anda mendapatkan pesan kesalahan "tidak dapat menemukan modul co" ...

TypeScript menjalankan pemeriksaan tipe penuh terhadap modul, jadi jika Anda tidak memiliki definisi TS untuk modul yang Anda coba impor (misalnya karena ini adalah modul JS tanpa file definisi), Anda dapat mendeklarasikan modul Anda dalam .d.tsfile definisi yang tidak tidak berisi ekspor tingkat modul:

declare module "co" {
    declare var co: any;
    export = co;
}
John Weisz
sumber
9
ini memberikan "tidak dapat menemukan co modul". Saya juga mencoba typings install coyang memberi Unable to find "co" in the registry. ada ide lain?
dcsan
Saya mengalami masalah yang sama dengan @dcsan yang dikatakan tidak dapat menemukan modul meskipun saya jelas sudah menginstalnya npm.
justin.m. mengejar
Ini mungkin disebabkan oleh jalur relatif. Saya tidak terbiasa dengan manajemen modul NodeJS, tetapi di RequireJS jika modul dirujuk secara relatif, folder saat ini harus dilambangkan secara eksplisit. Artinya, ./coalih-alih co, jika co.ts ada di folder yang sama (atau hasil kompilasi, co.js).
John Weisz
1
perhatikan, "* sebagai xxx" itu penting. Jadi, bukan "impor xxx dari ..." tetapi "impor * sebagai xxx dari ..."
Nurbol Alpysbayev
27

Penjelasan terbaik yang bisa saya dapatkan adalah dari postingan Tamas Piro .

TLDR; TypeScript menggunakan pengetikan DOM untuk lingkungan eksekusi global. Dalam kasus Anda, ada properti 'co' pada objek jendela global.

Untuk mengatasi ini:

  1. Ubah nama variabel, atau
  2. Gunakan modul TypeScript, dan tambahkan ekspor kosong {}:
export {};

atau

  1. Konfigurasi opsi kompiler Anda dengan tidak menambahkan pengetikan DOM:

Edit tsconfig.json di direktori proyek TypeScript.

{
    "compilerOptions": {
        "lib": ["es6"]
      }
}
Neville Omangi
sumber
ini untuk sisi klien? masalah asli saya adalah dengan kode sisi server dan saya tidak percaya opsi kompilator DOM sedang digunakan (proyek lama)
dcsan
1
Saya mengonfirmasi bahwa menambahkan export {}memang memecahkan masalah bagi saya, namun menambahkan "compilerOptions": { "lib": ["es6"] }TIDAK tampaknya membantu baik selama kompilasi maupun dalam VSCode.
adamsfamily
Tautan ke postingan asli sudah mati.
Cyclonecode
13

Saya menerima kesalahan serupa ini saat menyusun aplikasi Node.JS Typescript saya:

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

Perbaikannya adalah menghapus ini:

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

dan menggantinya dengan ini:

"compilerOptions": {
  "types": ["node"]
}
Tom Mettam
sumber
9

Gunakan IIFE(Immediately Invoked Function Expression), IIFE

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

 })();
Belter
sumber
Sederhana. Bekerja dengan sempurna. Terima kasih! (Dalam kasus saya, saya menyatakan const expect = chai.expect;untuk menggunakan tes Ketimun dalam proyek Angular 5).
Maxime Lafarie
7

Bagi mereka yang datang ke sini di usia ini, berikut adalah solusi sederhana untuk masalah ini. Setidaknya itu berhasil untuk saya di backend. Saya belum memeriksa dengan kode frontend.

Tambahkan saja:

export {};

di bagian atas kode Anda.

Penghargaan untuk EUGENE MURAVITSKY

Obinna Nnenanya
sumber
1

Saya mendapat masalah yang sama, dan solusi saya terlihat seperti ini:

// *./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();
        }
    }
}

Sekarang kita bisa menggunakannya di sisi server:

// *./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());

Dan di sisi klien juga:

// *./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

Dan, tentu saja, file gulp untuk semua ini:

// *./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);
})

Diperbarui. Tentu saja, tidak perlu mengompilasi file skrip secara terpisah. runSequence(['ts1', 'ts2', 'ts3'], 'browserify', callback)bekerja dengan sempurna.

django dev
sumber
7
Untuk berjaga-jaga jika ada yang menunda TypeScript karena verbositas dan pengulangan file gulp itu, tidak ada yang melakukan ini.
Daniel Earwicker
0

Saya mendapat kesalahan ini saat meningkatkan

gulp-typescript 3.0.2 → 3.1.0

Mengembalikannya ke 3.0.2 memperbaikinya

danday74
sumber
0

Dalam kasus saya, tsconfig.jsonmasalah yang diselesaikan berikut ini :

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

Seharusnya tidak ada type: moduledalam package.json.

Daniel
sumber