Skip to content

extends dynamic Base class with generic throw an error #8853

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

Closed
cevek opened this issue May 27, 2016 · 4 comments
Closed

extends dynamic Base class with generic throw an error #8853

cevek opened this issue May 27, 2016 · 4 comments
Labels
Duplicate An existing issue was already created

Comments

@cevek
Copy link

cevek commented May 27, 2016

Throw error: Base constructor return type 'T' is not a class or interface type

interface BaseClass<T> {
    new (): T
}
function generateUserClass<T>(baseClass: BaseClass<T>){
    return class extends baseClass {
        name: string;
    }
}

Error: Type any is not constructor function type

function generateUserClass<T>(baseClass: any){
    return class extends baseClass {
        name: string;
    }
}

But if we specify generic it's work

function generateUserClass(baseClass: BaseClass<Foo>){
    return class extends baseClass {
        name: string;
    }
}

Throw error: Base constructor return type 'IUser & Base' is not a class or interface type

interface IUser {
    name: string;
}
interface IUserClass<T>{
    new (): IUser & T;
}
function genUserCls<T>(base: new ()=>T): IUserClass<T> {
    return null;
}
class Base{
    foo(){}
}
class User extends genUserCls(Base) {}

TS version: 1.8

@cevek cevek changed the title extends dynamic Base class thrown an error extends dynamic Base class with generic thrown an error May 27, 2016
@cevek cevek changed the title extends dynamic Base class with generic thrown an error extends dynamic Base class with generic throw an error May 27, 2016
@sandersn
Copy link
Member

For the first example, on master, I get a different error:

interface I<T> {
    new(): T
}

function gen<T>(base: I<T>) {
    return class extends base {
                         ^^^^ Base constructor return type 'T' is not a class or interface type
        name: string;
    }
}

This error seems correct to me -- T is just a type variable, so we can't know if it's a class or not. However, adding a constraint doesn't make the error go away:

class Foo { }
function gen<T extends Foo>(base: I<T>) {
  return class extends base {
                       ^^^^ same error here
    name: string
  }
}

@mhegazy
Copy link
Contributor

mhegazy commented Jun 7, 2016

this is behaving as i would expect. you can only extend object types, in other words something that of a known structure. type arguments are not. the extend relationship involves checking that the structure of the derived class matches that of the base. without knowing what is the shape of the base, the compiler can not report these errors.

The request to allow classes to extend generic type arguments is tracked by #4890

@mhegazy mhegazy closed this as completed Jun 7, 2016
@mhegazy mhegazy added the Duplicate An existing issue was already created label Jun 7, 2016
@cevek
Copy link
Author

cevek commented Jun 7, 2016

Thanks, ahejlsberg example is working

interface Base{}
interface BaseClass<T> {
    new (): T
}

function generateUserClass<T extends Base>(baseClass: BaseClass<T>){
    class User extends (baseClass as BaseClass<Base>) {
        name: string;
    }
    return User as BaseClass<T & User>;
}

class Model{
    id: number;
}
var User = generateUserClass(Model);
var user = new User();
user.id;

@hszhsh
Copy link

hszhsh commented Oct 21, 2016

'new User()' is ok, but you cannot create a class that extends User.

@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
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

4 participants