TypeScript中的类构造函数

时间:2018-11-06 11:28:29

标签: angular typescript

我有以下C#类:

public class Envelope<T> {

  public List<Error> Errors { get; private set; } = new List<Error>();

  public Paging Paging { get; private set; }

  public List<T> Result { get; private set; } = new List<T>();


  public Envelope(T result) : this(new List<T> { result }, null, new List<Error>()) { }

  public Envelope(List<T> result) : this (result, null, new List<Error>()) { }

  public Envelope(List<Error> errors) : this(new List<T>(), null, errors) { }

  public Envelope(List<T> result, Paging paging, List<Error> errors) {

    Errors = errors;
    Paging = paging;
    Result = result;

  }

}

我需要在Angular 6项目上将此类转换为TypeScript,所以我这样做了:

export class Envelope<T> {

  errors: Error[];
  paging: Paging;
  result: T[];

  constructor(result: T[], paging: Paging, errors: Error[]) {

    this.errors = errors;
    this.paging = paging;
    this.result = result;

  }

}

问题在于Typescript不允许使用多个构造函数,因此似乎无法复制C#中我拥有的完全不同的构造函数。

有没有办法做到这一点?

信封应该是TypeScript中的接口吗?

Basically Envelope是API响应的包装,其中包含各种对象,例如结果本身,分页和可能的错误列表。

2 个答案:

答案 0 :(得分:4)

您可以创建构造函数重载,但是您必须在实现中手动区分它们。在您的情况下,实现的第一个参数将是T| T[] | Error[]的并集,并且您可以使用类型防护来手动区分并集中的情况:

function isErrorArray<T>(e: T | Error[]): e is Error[] {
    return e instanceof Array && e[0] && e[0] instanceof Error;
}
export class Envelope<T> {

    errors: Error[];
    paging: Paging;
    result: T[];

    constructor(result: T)
    constructor(errors: Error[])
    constructor(result: T[], paging: Paging, errors: Error[])
    constructor(result: T | T[] | Error[], paging?: Paging, errors?: Error[]) {
        if (isErrorArray(result)) {
            errors = result;
            result = [] as T[];
        }
        if (Array.isArray(result)) {

        } else {
            result = [result];
        }
        this.errors = errors;
        this.paging = paging;
        this.result = result; // result will be T[] because of the above ifs

    }

}

答案 1 :(得分:3)

给出您的代码,这应该可以工作,而且看起来更简单:

export class Envelope<T> {
  constructor(
    public result?: T[], 
    public paging?: Paging, 
    public errors: Error[] = null
  ) {}
}

您有简写方式:

  • 在构造函数参数之前附加的访问修饰符将声明类成员。因此,您无需在构造函数中实例化类成员。
  • 在成员名称后使用?使其成为可选,这意味着如果不提供它,则只需用undefined代替它的值即可。
  • 在函数(或构造函数)的参数中设置值可使该成员成为可选成员并为其提供默认值。

作为旁注,Typescript以一种奇怪的方式允许多个构造函数:

export class Envelope<T> {
  constructor(public result: T[])
  constructor(public paging: Paging)
  constructor(public errors: Error[])
  // ...
  {}
}

这种语法的问题是,您将必须使用instanceof测试每个参数,以查看它们是否属于期望的类型,我并不特别喜欢(对我来说,可选参数似乎更简单)< / p>