在命名空间打字稿项目中使用NPM模块

问题描述

我有一个项目(现有项目),其前端使用命名空间打字稿编写。 我无法将所有打字稿文件从命名空间方法重写为导出/导入es6语法。

但是下面的代码运行正常。如果我将我的新ts模块或react组件添加到命名空间中,并且将其包装在名称空间中并按Class调用,或者在其他名称空间中使用名称空间前缀,则没有问题。

问题是我不能使用带有import语句的外部模块。我如何使用..?因为import语句抛出错误

要针对下面的代码更具体,我想使用react-redux

当我检查node_moduels文件夹时,我在引用React名称间的地方看到了@types文件夹 我假设由于tsconfig中的这一行

"typeRoots": [
      "./node_modules/@types/"
    ]

但是当我安装npm install --save @types/react-redux时,它还在节点模块的@types文件夹下创建了带有index.ts的react-redux文件夹。但是它没有命名空间导出行,React类型文件内容如下所示。

export as namespace React;

declare namespace React {
....
}

最终..如何在该项目中使用第三方节点模块,尤其是react-redux。 或任何简单的节点模块,并以任何ts文件的简单模块(例如“ react-bootstrap”)访问它 以下是打包在namesapce中的react componnet的简单ts文件,该文件可以正常工作(导入台除外)

import { createStore } from 'redux'; //if i add this line this is throwing error.

namespace Profile.Sample {

    import { createStore } from 'redux'; //this too throwing error,without these lines my code is working fine.
    export class Profiles extends React.Component<any> {

        constructor(props) {
            super(props);           
            this.state = { brand: "Ford" };

        }     

        render(): React.ReactNode {

            return (
                <sect
                    <div className="container-fluid">
                        <div className="row">
                            <div className="col-lg-12">
                                <div className="main-title">
                                    <h2>Profiles</h2>
                                    <p>Lorem ipsum dolor sit amet,consectetur adi</p>
                                </div>
                            </div>
                        </div>
                        
                    </div>
                </section>

            );
        }
    }
}

下面是我的tsconfig

{
  "compileOnSave": true,"compilerOptions": {
    "preserveConstEnums": true,"experimentalDecorators": true,"declaration": true,"emitBOM": true,"jsx": "react","noEmitHelpers": true,"inlinesourceMap": true,"inlinesources": true,"outFile": "wwwroot/Scripts/site/Profiles.js","skipLibCheck": true,"skipDefaultLibCheck": true,"target": "es5","typeRoots": [
      "./node_modules/@types/"
    ]
  }
}

我知道不建议使用命名空间,..但这是一个现有项目,无法将所有文件从命名空间重写为导入/导出语句。

解决方法

好吧,让我们逐步使其可运行:

  1. 尽管您没有明确声明,但我假设您收到错误消息Cannot compile modules using option 'outFile' unless the '--module' flag is 'amd' or 'system'.。选项outFile生成一个主文件,其中包含所有代码。由于您在"target": "es5"中使用tsconfig.json,因此module的默认值为commonjscommonjs是广泛用于node.js(var x = require('x') / exports.x = x)的模块语法,该语法不支持将代码合并到一个文件中,因此被禁止。但是您想在浏览器中使用代码,因此无论如何commonjs都不被支持。所以要做的第一件事是

    "module": "AMD"插入您的tsconfig.json文件中。

    AMD是可在浏览器中使用的模块语法。您还可以使用"UMD"(这只是扩展名),以便该模块支持AMDcommonjs模块。

  2. 为避免以后再进行其他配置,您还应该

    "outFile": "wwwroot/Scripts/site/Profiles.js"文件中的"outDir": "wwwroot/Scripts/site"更改为tsconfig.json

  3. module设置为AMD会将moduleResolution的默认设置从node更改为classic,但这并不好,因为这样{{1 }}将失败,并显示错误消息import {createStore} from 'redux'。因此

    在您的Cannot find module 'redux'. Did you mean to set the 'moduleResolution' option to 'node',or to add aliases to the 'paths' option?文件中包含"moduleResolution": "node"

  4. 在您的代码中定义一个扩展了另一个基类的类。如果转换此继承,则需要特殊功能tsconfig.json。使用当前设置,此功能不是由打字稿生成的,并且会收到错误__extends。因此

    删除Uncaught ReferenceError: __extends is not defined

  5. 现在可以将所有文件转换为AMD模块。但是要使用这些模块,您需要一个模块加载器。最受欢迎的是require.js。要使用它,

    "noEmitHelpers": true插入HTML文件。

    您也可以download并自己提供。 <script data-main="setup" src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js" integrity="sha512-c3Nl8+7g4LMSTdrm621y7kf9v3SDPnhxLNhcjFJbKECVnmZHTdo+IRO05sNLTH/D3vA6u1X32ehoLC7WFVdheg==" crossorigin="anonymous"></script>表示在require.js加载后,脚本data-main="setup"被执行。该脚本将在下一步中创建。

  6. require.js需要一些配置才能找到所有模块。所以

    创建setup.js

    wwwroot\Scripts\site\setup.js

    在第一部分中,require.js被配置。特别是,定义了外部模块(通过requirejs.config({ appDir: ".",paths: { 'react': ['./node_modules/react/umd/react.production.min.js','https://unpkg.com/react@16/umd/react.production.min'],'react-dom': ['./node_modules/react-dom/umd/react-dom.production.min.js','https://unpkg.com/react-dom@16/umd/react-dom.production.min'],'redux': ['./node_modules/redux/dist/redux.min.js','https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min'],},}); requirejs(['entryPoint'],function() { console.log("Entry point 'index' has been loaded!"); return {}; }); 安装的模块)的位置。这里npmreactreact-dom的位置被设置为redux文件夹中的位置,其中包含来自内容分发网络(CDN)的外部文件作为备份。您也可以删除位置之一。它们从左到右被请求,如果一个请求失败,则继续前进。如果您使用node_modules文件夹中的位置,则还必须从Web服务器上为它们提供服务!

    在第二部分中,执行模块node_modules。这是您应用程序的入口点。将名称更改为任何您想作为入口点的名称。如果要将文件entryPoint中定义的模块作为入口点,请编写someOtherFile.js

  7. 要翻译所有文件,请运行

    requirejs(['someOtherFile'],...

  8. 服务目录tsc --project tsconfig.json中的所有文件,包括HTML文件。出于测试目的,您可以使用

    wwwroot/Scripts/site

您可以在此处查看经过稍微修改的代码:https://codesandbox.io/s/elated-fermat-ie2ms?file=/src/index.tsx