неможливо повторно оголосити змінну сфери дії блоку (машинопис)


99

Я будую додаток вузла, і всередині кожного файлу .js звикли робити це, щоб вимагати в різних пакетах.

let co = require("co");

Але отримання

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

і т. д. Отже, використовуючи машинопис, здається, що для всього проекту може бути лише одна така декларація / вимога? Я збентежений з цього приводу, оскільки вважав, що його letбуло застосовано до поточного файлу.

У мене щойно був проект, який працював, але після рефактора зараз я отримую ці помилки повсюдно.

Хтось може пояснити?


1
Як щодо цього - нехай co_module = require ("co"); Я зіткнувся з чимось подібним, і це вирішило помилку.
тиріон

1
Здається, це помилка машинопису. Я навів тут мінімальний приклад: gist.github.com/rjmunro/428ec644b6e53a499ca3a5ba8de2edc7
rjmunro,

5
Через 2,5 роки, і я повернувся до власного питання, це все ще проблема. на цей раз із вбудованими вузлами. const fs = require('fs')дає подібну помилку, тому не впевнений, з якої бібліотеки імпортувати це з ...
dcsan

Те, що ТС все ще робить це, смішно
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

У мене така ж проблема, як і у @dcsan, він каже, що не може знайти модуль, хоча я чітко його встановив npm.
justin.m.покупка

Це може бути спричинено відносним шляхом. Я не знайомий з управлінням модулями NodeJS, але в RequireJS, якщо на модулі посилаються відносно, поточна папка повинна бути чітко позначена. Тобто ./coзамість того co, якщо co.ts знаходиться в тій самій папці (або скомпільований результат, co.js).
Джон Вайс

1
будьте уважні, "* як xxx" важливо. Отже, не "імпортувати xxx з ...", а "імпортувати * як xxx з ..."
Нурбол Алписбаєв

27

Найкраще пояснення, яке я міг отримати, - із допису Тамаша Піро .

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

Посилання на оригінальний пост мертве.
Циклонекод

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).
Максим Лафарі

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)працює ідеально.


7
Про всяк випадок, якщо когось відбиває TypeScript за рахунок багатослівності та повторюваності цього ковткового файлу, ніхто цього не робить.
Даніель Ервікер

0

Я отримав цю помилку під час оновлення

gulp-typecript 3.0.2 → 3.1.0

Повернувши його до 3.0.2, це виправлено


0

У моєму випадку tsconfig.jsonвирішена така проблема:

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

Не повинно бути type: modulein package.json.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.