繁体   English   中英

扩展另一个类的数组和泛型类:是否可以在打字稿中使用?

[英]Arrays and generic classes that extends another class: Possible in typescript?

我有一个通讯录和两种类型的联系人:

  • 人数
  • 组织机构

它们都扩展了Contact类。


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

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

很好,但是如果我有该方法对数组中的Contacts的某些属性做些什么呢?

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]通用类型“数组”需要1个类型参数

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

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

contact.doSomething()//以两种方式实现的抽象方法

您可以使用已经拥有的相同方法,而无需“麻烦”的部分。

例如,如果您要过滤掉以字符串开头的联系人,则只需为Contact提供一个startsWith方法,并在所有子类中实现它,那么当您迭代联系人时,此方法始终可用,无需检查特定的类型:

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

由于您可能在基础Contact类中具有联系人姓名,因此仅出于示例目的,就不必抽象它。

如果需要对联系人进行不同的处理,则可以使用以下三种选择:

(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)具有不同的联系人“获取器”来过滤联系人数组:

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是因为:

操场上的代码

class A {}

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

您不能这样声明一个泛型签名,在示例打字稿中,您认为您想使用 Array的泛型签名,而T扩展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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM