从Angular项目

时间:2017-10-18 09:40:24

标签: angular typescript webpack typelite

在Angular项目中,我使用TypeLITE为来自后端的对象自动生成一堆接口。那部分效果很好,我对物体有智能感知,并且(在某种程度上)那些类型安全。

但现在我遇到了包含枚举的第一个类,TypeLITE正确地拾取并在enums.ts中创建TypeScript代码。这两个文件的内容如下所示:

classes.d.ts

declare namespace My.Multi.Level.Namespace {
  interface MyInterface {
    Status: My.Multi.Level.Namespace.Status;
  }
}

enums.ts

namespace My.Multi.Level.Namespace {
  export const enum Status {
    Undefined = 0,
    New = 1,
    ...
  } 
}

someOtherFile.ts

// How/what to import to access this?
const status = My.Multi.Level.Namespace.New;

引用该枚举的“classes.d.ts”中的实际接口仍然可以正常工作。

但现在我尝试导入该命名空间以在运行时访问“Status”枚举,并且无法弄清楚如何执行此操作。无论我做什么,命名空间都不可用。

我尝试将其更改为“export namespace ...”甚至“export module ...”但这会破坏“classes.d.ts”中生成的代码。我需要一个解决方案,允许我在运行时使用枚举,并保持与类完整的连接。

我理解在模块和命名空间方面存在一些不兼容性,但我只是假设有一些方法来解决它并实际使用这些枚举?

USED VERSION
Angular 4.3.6
TypeScript 2.3.4.

编辑:简化示例

如果您想在自己的机器上尝试我遇到的问题,请按以下步骤操作:

1)创建一个新的最小角度应用

ng new enumtest --minimal

2)使用以下代码修改app.component.ts文件:

import { Component, OnInit } from '@angular/core';
import { My } from './classes';

@Component({
  selector: 'app-root',
  template: `<p>{{myEnum}}</p>`
})
export class AppComponent implements OnInit {

  myEnum: My.Multi.Level.Namespace.Status;

  ngOnInit() {
    console.log("ngOnInit:begin:myEnum");
    this.myEnum = My.Multi.Level.Namespace.Status.New;
    console.log("ngOnInit:after:myEnum");
  }

}

3)添加此文件classes.ts

// classes part

namespace My.Multi.Level.Namespace {
  export interface MyInterface {
    Title: string;
    Status: My.Multi.Level.Namespace.Status;
  }
}
namespace My.Other.Multi.Level.Namespace {
  export interface SomeInterface {
    Context: My.Multi.Level.Namespace.MyInterface[];
  }
}

// enums part

namespace My.Multi.Level.Namespace {
  export const enum Status {
      Undefined = 0,
      New  = 1
  } 
}

export import My = My;

预期的行为:页面上将显示“1”(枚举的值)并且它仍然会编译,因为所有引用仍然完好无损(如My.Other.Multi.Level.Namespace.SomeInterface.Context仍然连接到My .Multi.Level.Namespace.MyInterface [])。

1 个答案:

答案 0 :(得分:1)

正如@Aleksey L.提到你需要export命名空间,它将适用于一个文件,但问题是每当你在顶层导出时,Typescript开始假设该文件是一个模块(并有充分理由)。

在Typescript中发明

Namespace是为了模仿假设在全局上的文件中的模块行为。

你几乎没有选择:

  1. 如果你不需要全局的命名空间,你可以摆脱它,并直接从每个文件导出枚举/接口。
  2. 如果你确实需要命名空间,那么它应该被导出,并且所有内容都应该写在同一个文件中,所以enum&amp;界面将在同一个文件中
  3. 实际上,在我的工作中,我们曾经大量使用过命名空间(当我们的所有代码库都在全局声明时),然后每当我们在构建系统中引入Webpack时,我们就开始将代码转换为使用 ES6模块,其中一个步骤是删除命名空间。

    我们要求逐步进行转换,因此部分代码使用了namespaces和一些ES6 modules。 为了保持向后兼容性,我们保留了包含命名空间的文件,并为每个文件创建了一个新文件,该文件从全局读取命名空间并将其导出到内部。

    类似的东西:

    // old-file.ts
    namespace someName {
       export class SomeClass {
    
       }
    }
    
    //old-file.es6.ts
    export import SomeClass = someName.SomeClass;
    

    希望有所帮助。