không thể khai báo lại biến phạm vi khối (chỉ định kiểu)


99

Tôi đang xây dựng một ứng dụng nút và bên trong mỗi tệp bằng .js đã từng làm việc này để yêu cầu trong các gói khác nhau.

let co = require("co");

Nhưng nhận được

nhập mô tả hình ảnh ở đây

vv Vì vậy, bằng cách sử dụng typecript có vẻ như chỉ có thể có một khai báo / yêu cầu như vậy trong toàn bộ dự án? Tôi bối rối về điều này vì tôi nghĩ letđã được xác định phạm vi đến tệp hiện tại.

Tôi vừa có một dự án đang hoạt động nhưng sau khi tái cấu trúc lại, tôi gặp những lỗi này khắp nơi.

Ai đó có thể giải thích?


1
Làm thế nào về điều này - let co_module = Required ("co"); Tôi đã đối mặt với một cái gì đó tương tự và điều này đã giải quyết được lỗi.
tyrion

1
Đây dường như là một lỗi sắp chữ. Tôi đã tạo một ví dụ tối thiểu ở đây: gist.github.com/rjmunro/428ec644b6e53a499ca3a5ba8de2edc7
rjmunro

5
2,5 năm sau và tôi quay lại câu hỏi của chính mình, đây vẫn là một vấn đề. lần này với nút tích hợp sẵn. const fs = require('fs')cho lỗi tương tự như vậy không chắc chắn những gì thư viện nhập khẩu từ ...
dcsan

Việc TS vẫn làm điều này thật nực cười
GN.

Câu trả lời:


67

Về bản thân lỗi, letđược sử dụng để khai báo các biến cục bộ tồn tại trong phạm vi khối thay vì phạm vi hàm. Nó cũng nghiêm ngặt hơn var, vì vậy bạn không thể làm những việc như thế này:

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

Cũng lưu ý rằng casecác mệnh đề bên trong switchkhối không tạo phạm vi khối của riêng chúng, vì vậy bạn không thể khai báo lại cùng một biến cục bộ trên nhiều cases mà không sử dụng {}để tạo từng khối.


Đối với quá trình nhập, bạn có thể gặp lỗi này vì TypeScript không nhận ra tệp của bạn là mô-đun thực và các định nghĩa cấp mô hình dường như cuối cùng trở thành định nghĩa chung cho nó.

Hãy thử nhập một mô-đun bên ngoài theo cách tiêu chuẩn của ES6 , không chứa chuyển nhượng rõ ràng và sẽ làm cho TypeScript nhận ra các tệp của bạn một cách chính xác dưới dạng mô-đun:

import * as co from "./co"

Điều này vẫn sẽ dẫn đến lỗi biên dịch nếu bạn đã có tên nào cođó, như mong đợi. Ví dụ, đây sẽ là một lỗi:

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

Nếu bạn gặp lỗi "không thể tìm thấy mô-đun co" ...

TypeScript đang chạy kiểm tra kiểu đầy đủ dựa trên các mô-đun, vì vậy nếu bạn không có định nghĩa TS cho mô-đun mà bạn đang cố gắng nhập (ví dụ: vì đó là mô-đun JS không có tệp định nghĩa), bạn có thể khai báo mô-đun của mình trong một .d.tstệp định nghĩa không 't chứa các xuất cấp mô-đun:

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

9
điều này cho "không thể tìm thấy co mô-đun". Tôi cũng đã thử typings install comà cho Unable to find "co" in the registry. bất kỳ ý tưởng nào khác?
dcsan

Tôi đang gặp vấn đề tương tự như @dcsan, nó nói rằng nó không thể tìm thấy mô-đun mặc dù tôi rõ ràng đã cài đặt npm.
justin.m.chase

Nó có thể do đường dẫn tương đối gây ra. Tôi không quen với quản lý mô-đun NodeJS, nhưng trong RequiJS nếu các mô-đun được tham chiếu tương đối, thì thư mục hiện tại phải được ký hiệu rõ ràng. Đó là, ./cothay vì co, nếu co.ts nằm trong cùng một thư mục (hoặc đầu ra đã biên dịch, co.js).
John Weisz

1
hãy chú ý, "* as xxx" là quan trọng. Vì vậy, không phải "nhập xxx từ ..." mà là "nhập * dưới dạng xxx từ ..."
Nurbol Alpysbayev

27

Lời giải thích tốt nhất mà tôi có thể nhận được là từ bài đăng của Tamas Piro .

TLDR; TypeScript sử dụng kiểu gõ DOM cho môi trường thực thi toàn cầu. Trong trường hợp của bạn, có một thuộc tính 'co' trên đối tượng cửa sổ toàn cầu.

Để giải quyết điều này:

  1. Đổi tên biến hoặc
  2. Sử dụng mô-đun TypeScript và thêm một tệp xuất trống {}:
export {};

hoặc là

  1. Định cấu hình các tùy chọn trình biên dịch của bạn bằng cách không thêm các kiểu in DOM:

Chỉnh sửa tsconfig.json trong thư mục dự án TypeScript.

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

cái này dành cho phía khách hàng? vấn đề ban đầu của tôi là với mã phía máy chủ và tôi không tin rằng các tùy chọn trình biên dịch DOM đang được sử dụng (dự án cũ)
dcsan 11/02/19

1
Tôi xác nhận rằng việc thêm export {}đã giải quyết được vấn đề cho tôi, tuy nhiên việc thêm "compilerOptions": { "lib": ["es6"] }dường như KHÔNG giúp ích gì trong quá trình biên dịch cả trong VSCode.
adamsfamily

Liên kết đến bài viết gốc đã chết.
Cyclonecode

13

Tôi đã gặp lỗi tương tự này khi biên dịch ứng dụng Node.JS Typescript của mình:

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

Cách khắc phục là loại bỏ điều này:

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

và thay thế nó bằng cái này:

"compilerOptions": {
  "types": ["node"]
}

9

Sử dụng IIFE(Immediately Invoked Function Expression), IIFE

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

 })();

Đơn giản. Hoạt động hoàn hảo. Cảm ơn bạn! (Trong trường hợp của tôi, tôi đã khai báo const expect = chai.expect;để sử dụng các bài kiểm tra Cucumber trong dự án Angular 5).
Maxime Lafarie 22/02/18

7

Đối với những người đến đây trong thời đại này, đây là một giải pháp đơn giản cho vấn đề này. Nó ít nhất đã làm việc cho tôi trong phần phụ trợ. Tôi chưa kiểm tra với mã giao diện người dùng.

Chỉ cần thêm:

export {};

ở đầu mã của bạn.

Ghi có vào EUGENE MURAVITSKY


1

Tôi gặp vấn đề tương tự và giải pháp của tôi trông như thế này:

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

Bây giờ chúng ta có thể sử dụng nó ở phía máy chủ:

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

Và về phía khách hàng nữa:

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

Và, tất nhiên, một tệp tin cho tất cả những điều này:

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

Đã cập nhật. Tất nhiên, không cần thiết phải biên dịch các tập tin typecript riêng biệt. runSequence(['ts1', 'ts2', 'ts3'], 'browserify', callback)hoạt động hoàn hảo.


7
Chỉ trong trường hợp bất kỳ ai bị loại bỏ TypeScript bởi tính dài dòng và lặp đi lặp lại của tệp gulp đó, không ai làm điều này.
Daniel Earwicker

0

Tôi gặp lỗi này khi nâng cấp

gulp-stylescript 3.0.2 → 3.1.0

Đưa nó trở lại 3.0.2 đã sửa nó


0

Trong trường hợp của tôi, tsconfig.jsonvấn đề sau đã được giải quyết:

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

Không nên có type: moduletrong package.json.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.