не может повторно объявить переменную с областью действия блока (машинописный текст)

99

Я создаю приложение узла, и внутри каждого файла в .js используется для этого в различных пакетах.

let co = require("co");

Но получение

введите описание изображения здесь

и т. д. Таким образом, при использовании машинописного текста кажется, что во всем проекте может быть только одно такое объявление / требование? Я смущен этим, так как думал, что letобласть действия ограничена текущим файлом.

У меня только что был проект, который работал, но после рефакторинга я теперь получаю эти ошибки повсюду.

Кто-нибудь может объяснить?

dcsan
источник
1
Как насчет этого - пусть co_module = require ("co"); Я столкнулся с чем-то похожим, и это устранило ошибку.
Тирион
1
Похоже, это ошибка машинописного текста. Я привел
rjmunro
5
2,5 года спустя, и я вернулся к своему собственному вопросу, это все еще проблема. на этот раз со встроенными узлами. const fs = require('fs')дает аналогичную ошибку, поэтому не уверен, из какой библиотеки импортировать это ...
dcsan 06
Тот факт, что TS все еще так поступает, просто смешон
GN.

Ответы:

67

Что касается самой ошибки, letиспользуется для объявления локальных переменных, которые существуют в областях видимости блока, а не в областях видимости функций. Он также более строгий var, поэтому вы не можете делать такие вещи, как:

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

Также обратите внимание, что caseпредложения внутри switchблоков не создают свои собственные области действия блока, поэтому вы не можете повторно объявить одну и ту же локальную переменную для нескольких cases, не используя {}для создания каждого блока.


Что касается импорта, вы, вероятно, получаете эту ошибку, потому что 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;
}
Джон Вайс
источник
9
это дает "не может найти модуль co". Я тоже пробовал, typings install coчто дает Unable to find "co" in the registry. любые другие идеи?
dcsan 03
У меня та же проблема, что и у @dcsan, он говорит, что не может найти модуль, хотя у меня явно установлен npm.
justin.m.chase
Это может быть связано с относительным путем. Я не знаком с управлением модулями NodeJS, но в RequireJS, если модули упоминаются относительно, текущая папка должна быть явно обозначена. То есть ./coвместо того co, чтобы co.ts находится в той же папке (или в скомпилированном выводе, co.js).
Джон Вайс
1
будьте внимательны, важно "* as xxx". Значит, не «импортировать xxx из ...», а «импортировать * как xxx из ...»
Нурбол Алпысбаев
27

Лучшее объяснение, которое я мог получить, - это сообщение Тамаса Пиро. .

TL; DR; 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...

 })();
Belter
источник
Просто. Прекрасно работает. Спасибо! (В моем случае я заявлял const expect = chai.expect;, чтобы использовать тесты Cucumber в проекте Angular 5).
Maxime Lafarie
7

Для тех, кто приходит сюда в эту эпоху, вот простое решение этой проблемы. По крайней мере, это сработало для меня в бэкэнде. Я не проверял код внешнего интерфейса.

Просто добавь:

export {};

вверху вашего кода.

Кредит ЕВГЕНИЮ МУРАВИЦКОМ

Обинна Нненанья
источник
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

И, конечно же, для всего этого gulp -файл:

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

Обновлено. Конечно, нет необходимости отдельно компилировать файлы машинописного текста. runSequence(['ts1', 'ts2', 'ts3'], 'browserify', callback)работает отлично.

django dev
источник
7
На всякий случай, если кого-то оттолкнет TypeScript из-за многословности и повторяемости этого файла gulp, никто этого не сделает.
Дэниел Эрвикер, 01
0

Я получил эту ошибку при обновлении

gulp-typescript 3.0.2 → 3.1.0

Вернув его в 3.0.2, исправил

danday74
источник
0

В моем случае tsconfig.jsonрешена следующая проблема:

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

Не должно быть type: modulein package.json.

Даниэль
источник