首页 文章

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

提问于
浏览
0

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

  • 组织

它们都延伸到了 Contact 类 .


我想要一个类的方法 return an array of contacts .

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

很好,但如果我有这个方法到数组内的 do something with some properties of the 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;

这感觉很麻烦,难以阅读 . Why not something like this?

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;

不可能,我 can't do this

Array<T extends Contact>

这个 error 由VSCode抛出:

[ts]通用类型'Array'需要1个类型的参数

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

2 回答

  • 0

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

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

    你可以使用你已经拥有的相同方式,没有“麻烦”的部分 .

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

    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

    您不能声明这样的通用签名,在您的示例中,typescript认为您要使用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;
    }
    

相关问题