Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
masonk opened this issue Dec 23, 2016 · 2 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@masonk
Copy link

masonk commented Dec 23, 2016

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);
@masonk
Copy link
Author

masonk commented Dec 23, 2016

I think I found the issue

@masonk masonk closed this as completed Dec 23, 2016
@RyanCavanaugh RyanCavanaugh added the Question An issue which isn't directly actionable in code label Dec 27, 2016
@bgever
Copy link

bgever commented May 24, 2017

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

@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

3 participants