Typescript: Argument of type 'typeof Cat' is not assignable to parameter of type 'new () => Cat'.

Created on 23 Dec 2016  路  2Comments  路  Source: microsoft/TypeScript

TypeScript Version: 2.1.4

Code

class Animal {
    // constructor() {} // (This constructor works)
    constructor(public p: string) {} // (This constructor errors)
}
class Cat extends Animal {}

declare function DecorateAnimal<T extends Animal>(original: { new(): T }): { 
    new(): T; 
};

let DecoratedCat = DecorateAnimal(Cat);

Expected behavior:
I expect to be able to pass typeof Cat to a function that takes a new(): Cat. I _can_ do that unless Animal has a property, then I can't. I would at the least expect it to work in both cases or in neither case.

Actual behavior:
Errors out with Argument of type 'typeof Cat' is not assignable to parameter of type 'new () => Cat'.

As motivation, this came up in the context of declaring the types of a decorator function. A JS library I'm using decorates classes, returning a new class which makes changes to both the static and instance side of a class type. Something like this:

class Animal<P> {
    constructor(public p: P) {}
}
class Cat extends Animal<string> {
    meow() {}
}
interface StaticDecorations<T> {
    originalClass: { new(): T };
}
interface InstanceDecorations<T> {
    originalInstance: T;
    makeTracks(): void;
}
declare function DecorateAnimal<T extends Animal<P>, P>(original: { new(): T }): { 
    new(): T & InstanceDecorations<T>; 
    prototype: { originalClass: { new(): T } }
};

let DecoratedCat = DecorateAnimal(Cat);
Question

Most helpful comment

I had a similar error. The reason was that I didn't set default values for the properties in the constructor, hence the parameterless new(): T won't match.

To fix the original example:

class Animal {
    // constructor() {} // (This constructor works)
    // constructor(public p: string) {} // (This constructor errors)
    constructor(public p = '') {} // (This constructor works)
}
class Cat extends Animal {}

declare function DecorateAnimal<T extends Animal>(original: { new(): T }): { 
    new(): T; 
};

let DecoratedCat = DecorateAnimal(Cat);

All 2 comments

I think I found the issue

I had a similar error. The reason was that I didn't set default values for the properties in the constructor, hence the parameterless new(): T won't match.

To fix the original example:

class Animal {
    // constructor() {} // (This constructor works)
    // constructor(public p: string) {} // (This constructor errors)
    constructor(public p = '') {} // (This constructor works)
}
class Cat extends Animal {}

declare function DecorateAnimal<T extends Animal>(original: { new(): T }): { 
    new(): T; 
};

let DecoratedCat = DecorateAnimal(Cat);
Was this page helpful?
0 / 5 - 0 ratings