Angular / Typescript class.name在生成版本中不起作用

时间:2018-02-13 03:37:04

标签: javascript angularjs typescript angular5

使用Angular 5.面对class.name属性的一个奇怪问题。我们在打字稿中有以下功能:

export class ApiService
{
  public list<T>(c: new(values: Object)=> T)
  {
    var cname = c.name;
    ....
  }
}

现在,如果我在Angular(ng-build)的dev构建中使用此函数,如下所示:

export class Employee()
{
    public id:string;
    public name: string;

    constructor(values: Object = {}) {          
       Object.assign(this, values);          
    }
}

在某处的代码中:

var list = api.list(Employee);

以上工作,在list函数中我得到cname ='Employee'

但是,如果我们使用ng build --env = prod构建此解决方案,代码将失败并且我们得到cname = undefined。

为什么会这样,以及如何解决?不应该在开发中编译和工作的东西,在生产中工作吗?

2 个答案:

答案 0 :(得分:1)

您可能会遇到缩小问题,这只会在prod版本中发生。缩小将重命名您的类,以实现最小的输出文件大小。

有关相关讨论,请参阅此问题和答案:Angular-cli : How to ignore class names from being minified

如上面的答案所提到的,为了配置此选项,您需要ng eject您的应用,这将允许您自定义UglifyJS选项(负责缩小的库),但这也将阻止您使用Angular CLI的一些不错的功能(如ng buildng serve)。

有关ng eject的说明,请参阅此GitHub评论:https://github.com/angular/angular-cli/issues/6302#issuecomment-301220770

答案 1 :(得分:0)

生产代码存在同样的问题,其中&#39; constructor.name&#39;正在返回一个空字符串。我的解决方案是装饰我需要的类,装饰者会重新分配名称&#39;在运行时使用任意类名或通过作为参数传递的一个:这里是装饰器:

import "reflect-metadata";
var __global__ClassName__id__ = 0;
export function ClassName(useThisName: string = null) {
    return function (target: any) {
       if (target.name.length === 0 || useThisName !== null) {
            Object.defineProperty(target, "name", {
                value: useThisName !== null ? useThisName : `__ClassName__${++__global__ClassName__id__}`,
                enumerable: false,
                writable: false,
                configurable: true
            });
        }
    }
}

代码看起来像这样:

// generate a dynamic class name
@Decorator.ClassName()
export class PopupMessage{ }

// uses the argument as class name
@Decorator.ClassName("PopupMessage")
export class PopupMessage{ }

// and code will work as usual
var something = new Message.PopupMessage(1);
var samething = (<any>something).constructor.name == Message.PopupMessage.name;