Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/36.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 将节点代码库迁移到TypeScript:全局范围?_Javascript_Node.js_Typescript - Fatal编程技术网

Javascript 将节点代码库迁移到TypeScript:全局范围?

Javascript 将节点代码库迁移到TypeScript:全局范围?,javascript,node.js,typescript,Javascript,Node.js,Typescript,我正在尝试将大型节点代码库迁移到TypeScript。为了让事情变得更简单,我只想先将.js文件重命名为.ts文件,修复任何语义问题,而无需进行太多重构,然后逐步改进代码库 我们考虑下面的例子: logger.js: exports = function(string) { console.log(string); } moduleA.js: var logger = require('./logger') exports.someAction = function() {

我正在尝试将大型节点代码库迁移到TypeScript。为了让事情变得更简单,我只想先将.js文件重命名为.ts文件,修复任何语义问题,而无需进行太多重构,然后逐步改进代码库

我们考虑下面的例子:

logger.js:

exports = function(string) {
    console.log(string);
}
moduleA.js:

var logger = require('./logger')    
exports.someAction = function() {
    logger.log('i'm in module a')
}
moduleB.js:

//var logger = require('./logger')    
exports.someOtherAction = function() {
    logger.log('i'm in module B')
}
moduleC.js:

var moduleA = require('./moduleA');  
var moduleB = require('./moduleB');  
exports.run = function(string) {
    moduleA.someAction();
    moduleB.someOtherAction(); //exception here - logger not defined
}
所以,如果我执行moduleB.someOtherAction(),我将得到一个异常,因为logger未在moduleB.js的作用域中定义

但typescript编译得很好,因为logger是在moduleA中声明的,这是因为(如果我理解正确的话)typescript将所有这些文件视为单个编译单元

那么,在不进行重构的情况下,有没有办法避免这种情况呢

更新

我已经创建了一个示例项目 如果我运行typescript编译器,我不会得到任何错误,尽管logger在moduleB.ts中被注释掉了:

g@w (master) ~/projects/ts-demo: gulp generate
[10:39:46] Using gulpfile ~/projects/ts-demo/gulpfile.js
[10:39:46] Starting 'generate'...
[10:39:46] Starting 'clean'...
[10:39:46] Finished 'clean' after 11 ms
[10:39:46] Starting '<anonymous>'...
[10:39:47] Finished '<anonymous>' after 1.4 s
[10:39:47] Finished 'generate' after 1.41 s
g@w (master) ~/projects/ts-demo: 
g@w(master)~/projects/ts演示:gulp生成
[10:39:46]使用gulpfile~/projects/ts demo/gulpfile.js
[10:39:46]正在启动“生成”。。。
[10:39:46]开始“清洁”。。。
[10:39:46]11毫秒后完成“清洁”
[10:39:46]开始':

如果您现在在同一个项目中创建一个新文件bar.ts,TypeScript类型系统将允许您使用foo.ts中的变量foo,就像它在全局可用一样

卢伊是对的。每个文件(使用CommonJS为节点编译时)都像其自己的模块一样创建。就像node中的正常情况一样

因此,要让它发挥作用,你可以这样做:

logger.ts

模块A.ts

模B.ts

模数

我还使用了tsconfig.json:

编译此文件(只需在包含tsconfig.json的文件夹中键入tsc)将导致每个.ts文件生成一个.js文件。它应该编译并运行得很好。在为node/CommonJS编译时,您需要从中获得的主要信息是,每个文件都是自己的自包含模块

由于有问题的编辑而进行编辑:

好的,再次查看您的代码后,有两个原因导致此编译无法正常运行:

  • 如果将一组文件发送到编译器,则所有这些文件中的所有引用以及全局范围中的所有变量都将在发送到编译器的所有.ts文件中可用。这令人困惑,有时令人遗憾,但目前情况就是这样。在您的情况下,这会导致node.d.ts中全局作用域中定义的
    require
    函数在所有.ts文件中可用,而不仅仅在moduleC.ts中可用;如果从moduleC.ts中删除引用,您将在logger.ts中获得错误,因为例如,未定义require函数。它还会导致logger.ts中定义的
    var logger=..
    在其他.ts文件中可用。Typescript假定它在运行时可用。。在为节点编译时,这并不理想,但在编写实际的typescript而不是试图编译纯javascript时,这不是问题。事实上,由于它是纯javascript,编译器不会将其识别为节点模块,而是将其视为通用javascript文件

  • 使用commonjs编译时,每个文件都由typescript编译器自己编译。如果找到任何引用或导入,那么这些引用或导入将被遵循并用于键入和验证代码,当然,但编译仍然是在每个文件的基础上进行的(
    var something=require(“./whatever”);
    不是导入,编译器会将其解释为由以字符串为参数的函数指定的变量。)

  • 这就是它编译的原因,让我们继续讨论它为什么不工作

    编译器在commonjs模式下输出的每个文件都是它自己的“节点模块”。如果您想从节点中的另一个模块中访问一个模块(这实际上与typescript无关,这只是节点的工作方式),则需要该文件。在moduleB.ts中(以及在moduleB.js中),没有指示节点说明记录器是什么。因此,您只需要要求记录器

    在您在第二次更新中提到的示例中,commonjs没有被使用,而且它与typescripts内部模块(而不是节点模块)有关,这是完全不同的事情

    因此,简单的答案是,如果您想使用节点中另一个节点中的一个文件,您必须需要它。只需在moduleB.ts中取消注释注释注释引用,就可以启动并运行所有内容

    在代码的当前状态下,typescript编译器对您帮助不大,因为它实际上不能。代码接近纯javascript,要从编译器获得适当的帮助,您需要开始将其转换为typescript。第一步可能是将
    var asdf=require(“”)替换为
    import asdf=require(“”),这将使编译器检查引用成为可能,并反过来帮助您


    我意识到这是一个冗长的回答,但你设法给自己制造了一个混乱和难以解释的行为

    在typescript中有一种叫做内部/外部模块的东西

    内部模块可以声明可以在项目中任何地方引用的内容。考虑键入/lib文件,您应该能够在项目中的任何地方引用
    Error
    String
    之类的内容

    另一方面,外部模块必须导入才能被引用。这就是你想要做的

    内部和外部模块之间的区别在于,外部模块使用
    导入
    导出
    。 内部使用
    声明模块/名称空间/var


    只需在
    tsconfig.json
    文件中添加
    “编译器选项”:{“模块”:“commonjs”}
    即可启用外部模块。

    这是错误的。Typescript将每个文件视为一个单独的单元。(声明文件除外)。是什么
    export default (str: string) => console.log(str);
    
    import logger from './logger';
    
    export var someAction = () => {
         logger("i'm in module a");
    }
    
    import logger from './logger';
    
    export var someOtherAction = () => {
        logger("i'm in module B");
    }
    
    import { someAction } from './moduleA';  
    import { someOtherAction } from './moduleB';
    
    someAction();
    someOtherAction();
    
    {
        "compilerOptions": {
            "module": "commonjs",
            "noImplicitAny": true
        },
        "files": [
            "logger.ts",
            "moduleA.ts",
            "moduleB.ts",
            "moduleC.ts"
        ]
    }