user2451322
user2451322

Reputation:

angular2 / typescript class inheritance with generic types

Hope one of you angular2 / typescript wizards can help out or at least provide a pointer in the right direction, before I got crazy :-)

Here is what I'd like to

In the below pseudo code example, I would like the call to the child's (inherited) someOtherfunction() to return "2"...

Am I asking for too much? I can't seem to find any decent examples on the web...

How do I get this right?

Thank you - Oliver

(CODE BELOW MAY BE BROKEN, IT'S JUST FOR ILLUSTRATION)

// 
// Parent Class
// 

export interface ICoreData <T> {
    observeItems: Observable <T[]> ;
    items: Array <T>;
}

@Injectable()
export class CoreData<T> implements ICoreData<T> {

    public observeItems: Observable<T[]>;
    private items: Array<T>;

    constructor( 'Dependency Injection...' ) {}

    coreFunction(): number {
        return 1;
    }
    someOtherfunction(){
        return this.coreFunction();
    }
}

// 
// Child class
// 

export interface IMyDataStructure {
    name: string;
    age: string;    
}

export interface ISpecificData extends ICoreData<IMyDataStructure> {
    someExtraKey: number;
}

@Injectable()
export class SpecificData extends CoreData<IMyDataStructure> implements ISpecificData {

    constructor() {
        super();
    }

    coreFunction(): number{
        // 
        // This function should "overwrite" the parent's original function 
        // and be called by the parent's someOtherfunction() function 
        // 
        return 2;
    }
}

Upvotes: 1

Views: 6541

Answers (1)

John Dibling
John Dibling

Reputation: 101456

You're not asking too much. However you can't use interfaces to accomplish what you're trying to accomplish. You need to extend a class, which can be generic.

An interface is simply a contract, or a blueprint if you like, for a data type. There is no functionality associated with an interface. However in your case you wanted to be able to have methods on the base class; methods you could override in the derived.

The way I usually do this is to declare an abstract base class (so that the base class can't be instantiated itself), and then extend classes from that. Here's an example:

Note, I've removed all the Angular2 cruft in order to keep the example as simple as possible.

abstract class Base<T> {
  constructor(public controlled: T) { }

  doIt(): string {
    return `Base.doIt: ${JSON.stringify(this.controlled)}`;
  }

  doSomethingElse(): string {
    return `Base.doSomethingElse: ${JSON.stringify(this.controlled)}`;
  }
};

interface Foo {
  foo: string;
  bar: string;
};

class Derived extends Base<Foo> {
  constructor(foo: Foo) {
    super(foo);
  }

  doSomethingElse(): string {
    return `Derived.doSomethingElse: ${JSON.stringify(this.controlled)}`;
  }
};

let d: Derived = new Derived({ foo: 'foo', bar: 'bar' });

console.log(`doIt ==> ${d.doIt()}`);
console.log(`doSomethingElse ==> ${d.doSomethingElse()}`);

Output:

doIt ==> Base.doIt: {"foo":"foo","bar":"bar"} 
doSomethingElse ==> Derived.doSomethingElse: {"foo":"foo","bar":"bar"}

Playground link.

Upvotes: 5

Related Questions