【问题标题】:Cannot redeclare block scoped variable无法重新声明块范围变量(打字稿)
【发布时间】:2016-06-15 23:26:26
【问题描述】:

我正在构建一个节点应用程序,并且在 .js 中的每个文件中习惯于在各种包中执行此操作。

let co = require("co");

但是得到

等等。所以使用打字稿似乎整个项目只能有一个这样的声明/要求? 我对此感到困惑,因为我认为 let 的范围仅限于当前文件。

我刚刚有一个正在运行的项目,但是在重构之后,现在到处都是这些错误。

谁能解释一下?

【问题讨论】:

  • 这个怎么样 - let co_module = require("co");我遇到了类似的事情,这解决了错误。
  • 这似乎是一个打字稿错误。我在这里做了一个最小的例子:gist.github.com/rjmunro/428ec644b6e53a499ca3a5ba8de2edc7
  • 2.5 年后,我又回到了自己的问题上,这仍然是一个问题。这次使用的是内置节点。 const fs = require('fs') 给出了类似的错误,所以不确定要从哪个库导入它...
  • TS 仍然这样做的事实是荒谬的
  • @rjmunro 但是你如何解决这个问题?

标签: typescript require


【解决方案1】:

关于错误本身,let 用于声明存在于block scopes 中的本地 变量,而不是函数范围。它也比var 更严格,所以你不能做这样的事情:

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

另请注意,switch 块内的 case 子句不会创建自己的块作用域,因此您不能在不使用 {} 为每个块创建块的情况下跨多个 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;

如果您收到错误“找不到模块合作”...

TypeScript 正在对模块进行完整的类型检查,因此如果您没有尝试导入的模块的 TS 定义(例如,因为它是没有定义文件的 JS 模块),您可以声明 em> 您的模块在不包含模块级导出的 .d.ts 定义文件中:

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

【讨论】:

  • 这给出了“找不到模块 co”。我还尝试了typings install co,它给出了Unable to find "co" in the registry。还有其他想法吗?
  • 我遇到了与@dcsan 相同的问题,它说即使我清楚地安装了 npm,它也找不到模块。
  • 可能是相对路径造成的。我对 NodeJS 的模块管理不熟悉,但是在 RequireJS 中,如果相对引用了模块,则必须明确表示当前文件夹。也就是说,./co 而不是 co,如果 co.ts 在同一个文件夹中(或编译输出,co.js)。
  • 注意,“* as xxx”很重要。所以,不是“import xxx from ...”而是“import * as xxx from ...”
  • 在将其添加到我的 tsconfig.json:"module": "commonjs" 之前,我无法在我的 nodejs 应用程序中使用导入。
【解决方案2】:

我能得到的最好解释来自Tamas Piro's post

TLDR; TypeScript 将 DOM 类型用于全局执行环境。在您的情况下,全局窗口对象上有一个“co”属性。

解决这个问题:

  1. 重命名变量,或

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

    export {};
    

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

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

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

【讨论】:

  • 这是给客户端的吗?我最初的问题是服务器端代码,我不相信正在使用 DOM 编译器选项(旧项目)
  • 我确认添加 export {} 确实解决了我的问题,但是在编译期间添加 "compilerOptions": { "lib": ["es6"] } 似乎在 VSCode 中也没有帮助。
  • 原帖链接已失效。
  • 这解决了我的问题,但我想知道他们必须做出这样决定的原因是什么。在文件上添加export {} 没有问题,但如果我有大约 30 个文件,那会很烦人。
  • @CyclonecodeCycle 链接现在正常运行
【解决方案3】:

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

只需添加:

export {};

在代码的顶部。

感谢EUGENE MURAVITSKY

【讨论】:

    【解决方案4】:

    我在编译我的 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"]
    }
    

    【讨论】:

      【解决方案5】:

      使用IIFE(Immediately Invoked Function Expression)IIFE

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

      【讨论】:

      • 简单。完美运行。谢谢! (在我的例子中,我声明 const expect = chai.expect; 是为了在 Angular 5 项目中使用 Cucumber 测试)。
      【解决方案6】:

      我在 vscode 上使用 ts 时也处理过这个问题。我解决此问题的方法很简单,但可能与您的问题不同。

      当我在最近的选项卡中同时打开 typescript 文件和 javascript 文件时,我的编辑器显示此错误。我只是关闭它,错误就消失了。

      希望这可以帮助那些可能也因这个简单的错误而摸不着头脑的人。

      【讨论】:

      • 解决问题的好答案,谢谢!只有在Vscode中同时打开.ts和.js文件时才会出现错误,关闭.js文件后问题就消失了。
      • 这个答案与那些从 ts 编译器得到错误的人无关
      【解决方案7】:

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

      TypeScript 文档似乎也推荐 ES Module 语法:TypeScript Modules

      当然还有很多,但作为一个开始:

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

        替换:

        const https = require('https');
        

        与:

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

        替换:

        module.exports = myVar ...
        

        与:

        export default myVar ...
        
      3. 将其他module.exports替换为export,例如

        替换:

        module.exports.myVar = 
        

        或:

        module.export = { myVar ... }
        

        与:

        export myVar ...
        

      更多:From CommonJS to ES Modules: How to modernize your Node.js app

      【讨论】:

        【解决方案8】:

        这是针对我的情况的解决方法。简单快捷!!!

        当块范围的变量在源代码的某处声明时会发生这种情况。

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

        【讨论】:

        • 即使您禁止在图像中发布代码,将我的 module.exports 替换为 export ... 为我消除了错误。
        【解决方案9】:

        我遇到了同样的问题,我的解决方案如下所示:

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

        已更新。 当然,没有必要单独编译 typescript 文件。 runSequence(['ts1', 'ts2', 'ts3'], 'browserify', callback) 完美运行。

        【讨论】:

        • 以防万一有人因为那个 gulp 文件的冗长和重复性而对 TypeScript 感到厌烦,没有人会这样做。
        【解决方案10】:

        在我的情况下,以下tsconfig.json 解决了问题:

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

        package.json 中不应有type: module

        【讨论】:

          【解决方案11】:

          就我而言(使用 IntelliJ)File - Invalidate Caches / Restart... 成功了。

          【讨论】:

          • WebStorm 2020.3 也是如此。这是正确解决方案的提示是它之前正在工作,并且在一些明显不相关的操作(例如,不相关的更改提交、推送等)之后开始出现错误
          【解决方案12】:

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

          【讨论】:

          • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
          【解决方案13】:

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

          “编译器选项”:{ “skipLibCheck”:真 }

          【讨论】:

          • 该选项与错误无关。我有那个选项,但我仍然收到错误。
          【解决方案14】:

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

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

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

          tsc --init 在主目录中。

          因为最初 typescript 将使用 JavaScript es5 并且无法理解最新的 JavaScript 语法。

          【讨论】:

            【解决方案15】:

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

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

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

            【讨论】:

              猜你喜欢
              • 2018-04-15
              • 1970-01-01
              • 2018-08-29
              • 2018-08-02
              • 2020-06-07
              • 2019-09-11
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多