0

I have an address book and two types of Contacts:

  • Persons
  • Organizations

Both of them extends Contact class.


I want a method of a class to return an array of contacts.

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

Nice, but what if i have that method to do something with some properties of the Contacts inside the array?

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;

This feels cumbersome, difficult to read. 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;

Impossible, i can't do this

Array<T extends Contact>

This error is thrown by VSCode:

[ts] Generic type 'Array' requires 1 type argument(s)

Is possible working with an array that uses a generic class that extends another class in typescript?

2 Answers 2

1

You seem to know the answer to your problem based on your question, as you wrote:

contact.doSomething() //abstract method implemented in both classes its own way

You can use the same way you already have, without the "cumbersome" part.

For example, if you want to filter out the contacts that start with a string then just have a startsWith method for Contact and implement it in all subclasses, then when you iterate the contacts this method is always available and there's no need to check the specific type:

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

Since you probably have the contact name in the base Contact class, there's no need for it to be abstract but just for the sake of the example.

In cases in which you need to treat the contacts differently you have 3 options:

(1) Check the type like you did:

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) Have different contact "getters" which filter the contacts array:

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) Have different data structures for the different types, and then do the same as in (2).

Another two comments on your code:

  • Inside your method use var or let for the contacts variable, otherwise you're polluting the global namespace

  • Use instanceof instead of typeof because:

(code in playground)

class A {}

let a = new A();
console.log(typeof a); // "object"
console.log(a instanceof A); // true
Sign up to request clarification or add additional context in comments.

Comments

0

You can not declare a generic signature like that, in your example typescript thinks that you want to use the generic signature of Array, and T extends Contact is not a type, it's a generic signature.

You can do it like this:

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;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.