编译时OK,在使用webpack的typescript中使用来自命名空间的类时出现运行时错误

时间:2016-12-22 06:29:31

标签: typescript webpack swagger-codegen

我使用swagger-codegen-l typescript-angular选项来生成REST使用者服务库。生成的代码如下所示(DefaultApi.ts):

namespace API.Client {
    'use strict';

    export class DefaultApi {
        protected basePath = 'http://localhost:7331/v1';
        public defaultHeaders : any = {};

        static $inject: string[] = ['$http', '$httpParamSerializer', 'basePath'];

        constructor(protected $http: ng.IHttpService, protected $httpParamSerializer?: (d: any) => any, basePath?: string) {
            if (basePath !== undefined) {
                this.basePath = basePath;
            }
        }

        private extendObj<T1,T2>(objA: T1, objB: T2) {
            for(let key in objB){
                if(objB.hasOwnProperty(key)){
                    objA[key] = objB[key];
                }
            }
            return <T1&T2>objA;
        }

        /**
         * Delete a person.
         * Deletes a specified individual and all of that person&#39;s connections. 
         * @param id The id of the person to delete
         */
        public deletePersonById (id: number, extraHttpRequestParams?: any ) : ng.IHttpPromise<{}> {/*...*/}

        /* etc... */
    }
}

如您所见,有些具体类需要使用,但是在命名空间内声明,即不能import能够。我的编辑器(VSCode)在我引用API.Client.DefaultApi时并没有抱怨,尽管缺少import,因为它将定义作为我认为的声明命名空间的一部分。但在运行时,浏览器抱怨API未定义。

我正在使用webpack捆绑我的代码。我在SO上看到了一些其他类似问题的问题,但是那里的答案没有运气。

编辑:

根据要求,这是我和ts和webpack的配置文件:

webpack配置文件:

const webpack = require('webpack');
const conf = require('./gulp.conf');
const path = require('path');

const HtmlWebpackPlugin = require('html-webpack-plugin');
const autoprefixer = require('autoprefixer');

module.exports = {
  module: {
    preLoaders: [
      {
        test: /\.ts$/,
        exclude: /node_modules/,
        loader: 'tslint'
      }
    ],

    loaders: [
      {
        test: /.json$/,
        loaders: [
          'json'
        ]
      },
      {
        test: /\.(css|less)$/,
        loaders: [
          'style',
          'css',
          'less',
          'postcss'
        ]
      },
      {
        test: /\.ts$/,
        exclude: /node_modules/,
        loaders: [
          'ng-annotate',
          'ts'
        ]
      },
      {
        test: /.html$/,
        loaders: [
          'html'
        ]
      }
    ]
  },
  plugins: [
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.NoErrorsPlugin(),
    new HtmlWebpackPlugin({
      template: conf.path.src('index.html')
    })
  ],
  postcss: () => [autoprefixer],
  debug: true,
  devtool: 'source-map',
  output: {
    path: path.join(process.cwd(), conf.paths.tmp),
    filename: 'index.js'
  },
  resolve: {
    modules: [
      path.resolve(__dirname, '../src/app'),
      path.resolve(__dirname, '../node_modules')
    ],
    extensions: [
      '',
      '.webpack.js',
      '.web.js',
      '.js',
      '.ts'
    ]
  },
  entry: `./${conf.path.src('index')}`,
  ts: {
    configFileName: '../tsconfig.json'
  },
  tslint: {
    configuration: require('../tslint.json')
  }
};

tsconfig.json:

{
  "compilerOptions": {
    "baseUrl": "src/app",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false,
    "module": "commonjs"
  },
  "compileOnSave": false,
  "include": [
    "src/**/*.ts"
  ],
  "exclude": [
    "!typings/**",
    "!node_modules/**"
  ]
}

2 个答案:

答案 0 :(得分:0)

当前版本的swagger-codegen TypeScript Angular生成器不会将DefaultApi包装在命名空间中。

更新并重新生成。如果您有任何问题,请告诉我。

答案 1 :(得分:0)

你有两个方法可以解决这个问题,一个简易方案和另一个复杂方案:

  1. 更改生成的ts文件。
  2. 在生成的代码末尾添加以下代码:

    export = API.Client;
    

    现在,您可以在模块中使用import而不会出现任何问题,例如:

    import {DefaultApi} from './generated-code';
    
    1. 但如果无法选择更改生成的文件,请求Salsa compiler
    2. 想法:

      使用不同的tsconfig拆分模块化代码而不是模块化代码。混合模块化代码,而不是模块化与Salsa,webpack解析别名和JavaScript支持。

      教程:

        

      TL; DR 这里有GitHub repository应用此解决方案。

      1. 创建一个新的tsconfig.generate.json来生成代码句柄,只需生成代码,例如:
      2. {
           "compilerOptions": {
              "outFile": "module-generated-code.js"
           },
           "files": ["generated-code.ts"]
        }
        
        1. 在您的初始tsconfig.json中,您必须排除生成的ts文件。这将确保没有不必要的代码,例如:
        2. {
             "compilerOptions": {
          
             },
             "exclude": ["generated-code.ts"]
          }
          
          1. 现在,洞中的王牌!您将添加api.js文件并在tsconfig.generate.json中引用它。是的,它是一个js文件,Salsa开始行动了。要执行此操作,您必须在tsconfig中启用allowJs功能
          2. { 
               "compilerOptions": {
                  "outFile": "module-generate-code.js", "allowJs": true
               },
               "files": ["generated-code.ts", "api.js"]
            }
            

            这些文件基本上是通过commonjs导出生成的代码而不触摸它。

            /// <reference path="./namespacing-code.ts" />
            // typescript compiler don't warning this because is Salsa!
            module.exports = API.Client;
            

            现在,请注意tsconfig.generate.json和您的outFile媒体资源。如果您测试编译器(tsc -p tsconfig.generate.json),则会在module-generate-code.js中看到所有生成的文件连接在一起,最后一行必须如下所示:

            module.exports = API.Client;

            差不多完成了!

            现在,您可以在自己的代码module-generate-code.js中使用import!但是js文件怎么没有最好的定义,那么你在webpack.config和tsconfig.json中配置了resolve.alias

            { //webpack.config
                resolve: {
                  extensions: ['', '.webpack.js', '.web.js', '.ts', '.js'],
                  alias:{ 'api':'./module-generated-code.js'
                }
            }
            
            { //tsconfig.json
                "compilerOptions": {
                    "allowJs": true, //remember of enabling Salsa here too
                    "baseUrl": ".",
                    "paths": {
                        "api":["api.js"] //it is just get type definitions from generated files
                    }
                 },
            

            现在,您无需触摸即可使用生成代码:import api from 'api';

            有任何疑问,这是使用这种方法的GitHub回购。 我希望我已经帮助了