无法重新声明块作用域变量

我正在构建一个节点应用程序,在. js 中的每个文件中,都需要在不同的包中执行此操作。

let co = require("co");

但是

enter image description here

那么使用打字稿似乎在整个项目中只能有一个这样的声明/要求? 我对此感到困惑,因为我认为 let的作用域是当前文件。

我只有一个项目是工作,但重构后,现在得到这些错误到处都是。

有人能解释一下吗?

251484 次浏览

关于错误本身,let用于声明 块状探测器中存在的 本地变量,而不是函数作用域。它也比 var严格,所以你不能这样做:

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

还要注意,switch块中的 case子句不会创建它们自己的块作用域,所以如果不使用 {}创建每个块,就不能跨多个 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;

如果你得到一个错误 “找不到 CO 模块”..。

TypeScript 正在对模块进行全面的类型检查,所以如果您没有要导入的模块的 TS 定义(例如,因为它是一个没有定义文件的 JS 模块) ,您可以在一个不包含模块级导出的 .d.ts定义文件中对模块进行 声明:

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

我也有同样的问题,我的解决方案是这样的:

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

当然,没有必要分别编译打印脚本文件。 runSequence(['ts1', 'ts2', 'ts3'], 'browserify', callback)运行正常。

使用 IIFE(Immediately Invoked Function Expression)生命

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


})();

我能得到的最好解释是来自 塔马斯 · 皮罗的帖子

极低密度辐射; TypeScript 对全局执行环境使用 DOM 类型。在您的示例中,全局窗口对象上有一个“ co”属性。

为了解决这个问题:

  1. 重命名变量,或者

  2. 使用 TypeScript 模块,并添加一个空导出{} :

    export {};
    

    或者

  3. 通过不添加 DOM 类型来配置编译器选项:

在 TypeScript 项目目录中编辑 tsconfig.json。

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

在编译 Node.JS 类型脚本应用程序时,我收到了类似的错误:

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"]
}

对于那些在这个时代来到这里的人,这里有一个简单的解决方案。至少在后台对我有用。我还没有检查前端代码。

只要加上:

export {};

在没有现有导出的任何代码的文件的顶部。

归功于 EUGENE MURAVITSKY

在我的案例中,tsconfig.json解决了以下问题:

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

package.json中应该没有 type: module

在我的案例中(使用 IntelliJ) File-Invalidate Caches / Restart...起到了作用。

这是我的解决方案,简单而快速! ! !

enter image description here

当块作用域变量在源代码中某处声明时会发生这种情况。

要解决这个问题,请删除 module.exports =并替换为 export default

只需在 TSconfig 文件中添加以下行即可

“编译器选项”: { “ skipLibCheck”: 正确 }

我在处理 vscode 时也处理过这个问题。我解决这个问题的方法很简单,但可能和你的问题不一样。

当我在最近的选项卡中同时打开打印脚本文件和 javascript 文件时,我的编辑器会显示这个错误。我只要关上它,错误就会消失。

希望这可以帮助那些可能因为这个简单的错误而挠头的人。

最简单的解决方案是更改:

"target": "es5""target": "es6"tsconfig.json文件。

如果无法访问此文件,请运行:

主目录中的 tsc --init

因为最初的打印脚本将被放置在 JavaScriptes5中,而且它不能理解最新的 JavaScript 语法。

当变量 co 已经在作用域中定义(可能 window/global 对象已经定义了它)并且您再次使用相同的名称声明变量时,就会发生这种情况。

如果您使用 var 替换 let,那么它不会给出错误,但是因为您使用 let,所以不允许使用 let 重新声明相同的变量

将变量重命名为别的名称,错误就会消失。

我的解决方案是将我的代码从使用 CommonJS (requiremodule.exports等)转换为 ES 模块(importexport等)

TypeScript 文档似乎也推荐 ES 模块语法: TypeScript 模块

当然,这里面还有更多的东西,但是作为一个开始:

  1. require的实例替换为 import,例如。

    更换:

    const https = require('https');
    

    配合:

    import https from 'https';
    
  2. 将默认的 module.exports替换为 export default,例如。

    更换:

    module.exports = myVar ...
    

    配合:

    export default myVar ...
    
  3. export代替其他 module.exports,例如。

    更换:

    module.exports.myVar =
    

    或:

    module.export = { myVar ... }
    

    配合:

    export myVar ...
    

详情请浏览: 从 CommonJS 到 ES 模块: 如何更新 Node.js 应用程序

这是编辑器的警告,因为当您打开了已编译的 index.js 和 index.ts 时。你会看到这个的。.但是当你关闭 index.js 的时候就没事了。

当我不正确地导入 express时,我得到了类似的错误。 我所要做的就是替换

const router = require('express').Router();

import express from 'express';
const router = express.Router();

在我的例子中,我使用的是角度,我试图在一个方法中用冒号而不是等号赋值一个变量,像这样:

const user$ : this.service.getUser();

应该是这样的:

const user$ = this.service.getUser();

另一种解决方案

IIFE 功能及关闭

Demot

// 1. namespace function
namespace a {
const func = () => {
//
}
}


// 2. function
const test = () => {
//
}

Demo.js


"use strict";
// 1. namespace function
var a;
(function (a) {
const func = () => {
//
};
})(a || (a = {}));


// 2. function
const test = () => {
//
};


裁判

Https://www.typescriptlang.org/docs/handbook/namespaces.html

Https://www.typescriptlang.org/docs/handbook/namespaces-and-modules.html

在我的例子中,重构使用名称空间解决了大多数问题

enter image description here

所以... 我做了一些事,似乎解决了问题,但我不确定看不见的后果,但似乎真的很简单。

我只是把{放在文件的开头,}放在结尾,因此在文件中创建了一个新块..。

File1.ts

{
let co=require('co');
//...
module.exports=...
}

File2.ts

let co=require('co');
let f1=require('./file1');
//...
module.exports=...

今天的日期是12月22日

例如:

 button const =() {}
export default button;


export const button2(){}
        

——————进口——————

import button, {ButtonIcon} from '../Button';