扩展另一个类的数组和泛型类:在打字稿中可能吗?

时间:2016-07-09 06:16:46

标签: typescript angular

我有一个地址簿和两种类型的联系人:

  • 组织

他们都扩展了联系类。

我想要一个类的方法来返回一个联系人数组

public method(args...): Array<Contact> {...}

很好,但是如果我有这种方法对数组中的某些属性做一些事情会怎么样?

public method(args...): Array<Contact> {
  contacts :Array<Contact> = getContactsFromSomewhere();
  contacts.forEach( contact => {
    if(typeof contact === "Person"){ //persons and organizations are different, they have different atrributes
      //Here i modify some Person attributes
    }
    else{
      //Here i modify some Organization attributes
  });
  return contacts;

这感觉很麻烦,难以阅读。 为什么不这样?

public method(args...): Array<T extends Contact> {
  contacts :Array<T extends Contact> = getContactsFromSomewhere();
  contacts.forEach( contact => {
    contact.doSomething() //abstract method implemented in both classes its own way.
  });
  return contacts;

不可能,我无法做到这一点

Array<T extends Contact>

VSCode抛出此错误

  

[ts] Generic type&#39; Array&#39;需要1个类型的参数

是否可以使用一个使用泛型类的数组来扩展typescript中的另一个类?

2 个答案:

答案 0 :(得分:1)

您似乎根据自己的问题知道问题的答案,如您所写:

  

contact.doSomething()//在两个类中实现的抽象方法   自己的方式

您可以使用与现有相同的方式,而不会使用“繁琐”的部分。

例如,如果要过滤掉以字符串开头的联系人,那么只需要startsWith Contact方法并在所有子类中实现它,然后在迭代联系人时使用此方法始终可用,无需检查具体类型:

public startsWith(prefix: string): Array<Contact> {
    return getContactsFromSomewhere().filter(contact => contact.startsWith(prefix));
}

由于你可能在基础Contact类中有联系人名称,因此不需要它是抽象的,只是为了示例。

如果您需要以不同方式处理联系人,则有3个选项:

(1)检查你的类型:

public sizeGreaterThan(min: number): Array<Contact> {
    return getContactsFromSomewhere().filter(contact => {
        if (contact instanceof Person) {
            return min === 1;
        } else {
            return (contact as Organization).size() >= min;
        }
    });
}

(2)有不同的联系人“getters”过滤联系人数组:

function getOrganizations(contacts: Contact[]) {
    return contacs.filter(contact => contact instanceof Organization);
}

public sizeGreaterThan(min: number): Array<Contact> {
    return getOrganizations(getContactsFromSomewhere()).filter(organization => organization.size() >= min);
}

(3)针对不同类型具有不同的数据结构,然后执行与(2)中相同的数据结构。

对您的代码另外两条评论:

  • 在您的方法中使用varlet作为contacts变量,否则您将污染全局命名空间

  • 使用instanceof代替typeof,因为:

code in playground

class A {}

let a = new A();
console.log(typeof a); // "object"
console.log(a instanceof A); // true

答案 1 :(得分:0)

您不能声明这样的通用签名,在您的示例打字稿中认为您想要使用 Array的通用签名,并且 T extends Contact 不是类型,它是一个通用的签名。

你可以这样做:

public method<T extends Contact>(...args): Array<T>
{
    var contacts: Array<T> = getContactsFromSomewhere();
    contacts.forEach( contact => {
        contact.doSomething() //abstract method implemented in both classes its own way.
    });
    return contacts;
}