James Wilkins
James Wilkins

Reputation: 7357

Derived typescript class type not accepted as it's own base type

I have a bit of code that should work, but I realize now doesn't because the constructor signatures are different for the types.

Example:

module test {
    export class A {
        constructor(a: string, b: string) { }

        static doSomething(a: typeof A): number { return 0; }
    }
}

module test {
    export class B extends A {
        constructor() { super("0", "1"); }
    }

    export class C extends B {
        static n = A.doSomething(C);
        x: number;

        constructor(c: C) { super(); }
    }
}

'A.doSomething(C)' fails because the constructors are not compatible between the types (because one type value must properly represent the two types in case 'new' is used). I know the REASON why, but is there no way (other than duck-typing) to specify a specific base type required? If not, this is a big limitation in my books, and there needs to be a "baseof" besides just "typeof". If duck-typing is required, then the answer is simply "no". ;)

Upvotes: 1

Views: 1334

Answers (2)

James Wilkins
James Wilkins

Reputation: 7357

Yes, I know one way to solve the issue is to put "<any>" before the type, so

A.doSomething(<any>C);

or

A.doSomething(<A><any>C);

Edit:

The only solution I found was to make the constructor parameters the same for at least the first 2 parameters, which is a compromise that works fine for my situation ...

module test {
    export class A {
        constructor(a: string, b: string) { }

        static doSomething(a: typeof A): number { return 0; }
    }
}

module test {
    export class B extends A {
        constructor(a: string, b: string) { super(a, b); }
    }

    export class C extends B {
        static n = A.doSomething(C);
        x: number;

        constructor(a: string, b: string, c?: C) { super(a, b); }
    }
}

Upvotes: 1

Jeffery Grajkowski
Jeffery Grajkowski

Reputation: 4061

So the error makes sense. To qualify as a typeof A in your example you must satisfy two conditions:

  1. Have a function doSomething that takes in a typeof A and returns a number
  2. Have a 'newable' function that takes in two strings and returns an A

typeof C just doesn't match that interface on the second point. The problem isn't expressing what you're trying to do.

What I would do is create an interface that represents the set of features you're requiring the input of doSomething to have to get its job done. It doesn't matter that typeof A wasn't explicitly created to implement that interface. If it matches everything that's asked for, you can pass it in.

Here's your example reworked:

// This is the important bit here
interface DoSomethingParam {
    doSomething(a: DoSomethingParam): number;
}

module test {
    export class A {
        constructor(a: string, b: string) { }

        static doSomething(a: DoSomethingParam): number { return 0; }
    }
}

module test {
    export class B extends A {
        constructor() { super("0", "1"); }
    }

    export class C extends B {
        static n = A.doSomething(C);
        x: number;

        constructor(c: C) { super(); }
    }
}

Upvotes: 0

Related Questions