no se puede volver a declarar la variable de ámbito de bloque (mecanografiado)

99

Estoy construyendo una aplicación de nodo, y dentro de cada archivo en .js solía hacer esto para requerir en varios paquetes.

let co = require("co");

Pero conseguir

ingrese la descripción de la imagen aquí

etc. Entonces, usando mecanografiado, parece que solo puede haber una declaración / requerimiento de este tipo en todo el proyecto. Estoy confundido acerca de esto, ya que pensé que letestaba en el ámbito del archivo actual.

Acabo de tener un proyecto que estaba funcionando, pero después de una refactorización ahora recibo estos errores por todas partes.

¿Alguien puede explicarlo?

dcsan
fuente
1
¿Qué tal esto? Let co_module = require ("co"); Me enfrenté a algo similar y esto solucionó el error.
tyrion
1
Esto parece ser un error mecanografiado. He hecho un ejemplo mínimo aquí: gist.github.com/rjmunro/428ec644b6e53a499ca3a5ba8de2edc7
rjmunro
5
2.5 años después y estoy de vuelta en mi propia pregunta, esto sigue siendo un problema. esta vez con nodos incorporados. const fs = require('fs')da un error similar, así que no estoy seguro de qué biblioteca importar esto ...
dcsan
El hecho de que TS todavía haga esto es ridículo
GN.

Respuestas:

67

Con respecto al error en sí, letse utiliza para declarar variables locales que existen en ámbitos de bloque en lugar de ámbitos de función. También es más estricto que var, por lo que no puedes hacer cosas como esta:

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

También tenga en cuenta que las casecláusulas dentro de los switchbloques no crean sus propios ámbitos de bloque, por lo que no puede volver a declarar la misma variable local en varios cases sin usar {}para crear un bloque cada una.


En cuanto a la importación, es probable que reciba este error porque TypeScript no reconoce sus archivos como módulos reales, y aparentemente las definiciones a nivel de modelo terminan siendo definiciones globales para él.

Intente importar un módulo externo de la forma estándar ES6 , que no contiene una asignación explícita, y debería hacer que TypeScript reconozca sus archivos correctamente como módulos:

import * as co from "./co"

Esto aún resultará en un error de compilación si ya tiene algo nombrado co, como se esperaba. Por ejemplo, esto será un error:

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

Si recibe un error "no se puede encontrar el módulo co" ...

TypeScript está ejecutando una verificación de tipos completa contra los módulos, por lo que si no tiene definiciones de TS para el módulo que está intentando importar (por ejemplo, porque es un módulo JS sin archivos de definición), puede declarar su módulo en un .d.tsarchivo de definición que no no contienen exportaciones a nivel de módulo:

declare module "co" {
    declare var co: any;
    export = co;
}
John Weisz
fuente
9
esto da "no se puede encontrar el módulo co". También probé lo typings install coque da Unable to find "co" in the registry. alguna otra idea?
dcsan
Tengo el mismo problema que @dcsan, dice que no puede encontrar el módulo aunque claramente lo tengo instalado npm.
justin.m.chase
Puede ser causado por la ruta relativa. No estoy familiarizado con la gestión del módulo NodeJS, pero en RequireJS si se hace referencia a los módulos de forma relativa, la carpeta actual debe indicarse explícitamente. Es decir, en ./colugar de cosi co.ts está en la misma carpeta (o la salida compilada, co.js).
John Weisz
1
esté atento, "* as xxx" es importante. Entonces, no "importar xxx desde ..." sino "importar * como xxx desde ..."
Nurbol Alpysbayev
27

La mejor explicación que pude obtener es la publicación de Tamas Piro .

TLDR; TypeScript utiliza las tipificaciones DOM para el entorno de ejecución global. En su caso, hay una propiedad 'co' en el objeto de ventana global.

Para solucionar esto:

  1. Cambiar el nombre de la variable, o
  2. Use módulos de TypeScript y agregue una exportación vacía {}:
export {};

o

  1. Configure las opciones de su compilador sin agregar tipos de DOM:

Edite tsconfig.json en el directorio del proyecto de TypeScript.

{
    "compilerOptions": {
        "lib": ["es6"]
      }
}
Neville Omangi
fuente
esto es para el lado del cliente? mi problema original era con el código del lado del servidor y no creo que se estuvieran usando las opciones del compilador DOM (proyecto antiguo)
dcsan
1
Confirmo que agregar export {}me resolvió el problema, sin embargo, agregar "compilerOptions": { "lib": ["es6"] }NO parece ayudar ni durante la compilación ni en VSCode.
adamsfamily
El enlace a la publicación original está muerto.
Cyclonecode
13

Recibí este error similar al compilar mi aplicación Typecript Node.JS:

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

La solución fue eliminar esto:

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

y reemplazarlo con esto:

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

Uso IIFE(Immediately Invoked Function Expression), IIFE

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

 })();
Belter
fuente
Sencillo. Funciona perfectamente. ¡Gracias! (En mi caso, estaba declarando const expect = chai.expect;para usar las pruebas de Cucumber en el proyecto Angular 5).
Maxime Lafarie
7

Para aquellos que vienen aquí en esta era, aquí hay una solución simple a este problema. Al menos funcionó para mí en el backend. No he comprobado con el código de la interfaz.

Solo agrega:

export {};

en la parte superior de su código.

Crédito a EUGENE MURAVITSKY

Obinna Nnenanya
fuente
1

Tengo el mismo problema y mi solución se ve así:

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

Ahora podemos usarlo en el lado del servidor:

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

Y del lado del cliente también:

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

Y, por supuesto, un archivo gulp para todo esto:

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

Actualizado. Por supuesto, no es necesario compilar archivos mecanografiados por separado. runSequence(['ts1', 'ts2', 'ts3'], 'browserify', callback)funciona perfecto.

dev django
fuente
7
En caso de que alguien se desanime de TypeScript por la verbosidad y la repetitividad de ese archivo gulp, nadie hace esto.
Daniel Earwicker
0

Recibí este error al actualizar

gulp-mecanografiado 3.0.2 → 3.1.0

Poniéndolo de nuevo a 3.0.2 lo solucionó

danday74
fuente
0

En mi caso, el siguiente tsconfig.jsonproblema resuelto:

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

No debería haber type: modulein package.json.

Daniel
fuente