Skip to content

Can't typecheck constructor in class generic parameter #23264

Closed
@albyrock87

Description

@albyrock87

TypeScript Version: 2.8.1

Search Terms: generics constructor type check constraint new

Code

export interface HasOneParameterConstructor<T> {
  new (p1: any): T;
}

class Foo {
  constructor(p1: string) {

  };
}

class Bar<T extends HasOneParameterConstructor<T>> {

}

class BarFooImpl extends Bar<Foo> { // error here under "Foo"

}

Expected behavior:
No errors: constructor type checking works

Actual behavior:
error TS2344: Type 'Foo' does not satisfy the constraint 'HasOneParameterConstructor'.
Type 'Foo' provides no match for the signature 'new (p1: any): Foo'.

Playground Link: Playground Test

Related Issues:
Maybe it's related to: Can't extend mixin constructor that constructs a generic type

Activity

changed the title [-]Can't typecheck constructor in generic parameter[/-] [+]Can't typecheck constructor in class generic parameter[/+] on Apr 9, 2018
ghost

ghost commented on Apr 9, 2018

@ghost

The problem is that an Foo is not HasOneParameterConstructor because you can't call new on an instance of Foo. You need to have separate types for the instance and class type.

class Bar<Instance, Class extends HasOneParameterConstructor<Instance>> {}
class BarFooImpl extends Bar<Foo, typeof Foo> {}
ghost added
QuestionAn issue which isn't directly actionable in code
on Apr 9, 2018
albyrock87

albyrock87 commented on Apr 10, 2018

@albyrock87
Author

Hi @Andy-MS , I tried your suggestion but the problem persists:

export interface HasOneParameterConstructor<T> {
  new (p1: any): T;
}

export abstract class ConstructorCheck<T, Class extends HasOneParameterConstructor<T>> {
  
}

export abstract class MyBase<TImplementor> extends ConstructorCheck<TImplementor, typeof TImplementor> {

}

class BaseImpl extends MyBase<BaseImpl> {

}

Your example does work but it's hackable:

class Hack { constructor(a: string) {} }
class BarFooImpl extends Bar<Foo, typeof Hack> {}

I'm trying to create a library with some usage restriction, and that's not good.

ghost

ghost commented on Apr 10, 2018

@ghost

Note that TypeScript does not have any abstract static methods (#14600). It might be more helpful to determine what you're trying to accomplish -- currently Class is unused there. Note that the type parameter is only available as a type, and not as a value, so you won't be able to write new T inside of your class body, and as you've noticed typeof T doesn't work.

albyrock87

albyrock87 commented on Apr 14, 2018

@albyrock87
Author

Basically I want to stop the developer to define a new constructor for BaseImpl. This way I can create new Instances of BaseImpl using exactly the MyBase constructor.

ghost

ghost commented on Apr 16, 2018

@ghost

If I understand that right, you want something like this?

abstract class A {
	final constructor() {}
}

class B extends A {
	constructor() { super(); someBadThing(); } // Compile error, super constructor is final
}

It doesn't seem that useful to have an abstract class whose constructor can't be overridden -- sublcass constructors are forced to call the superclass constructor anyway. And one can of course do new B(); b.someBadThing(); even if the constructor isn't overridden.

albyrock87

albyrock87 commented on Apr 16, 2018

@albyrock87
Author

A final constructor would do the trick.
I'm in the Angular world, and I'm trying to stop the developer to @Inject other things in the B class.

ghost

ghost commented on Apr 16, 2018

@ghost

This is a duplicate of #1534 then -- I don't think there's a good way to do what you want right now. (You can't just make the constructor private because then the class can't be overridden at all.) It's possible that you could add a run-time check in A's constructor that this.constructor has no decorators? I don't really know how angular works though.

typescript-bot

typescript-bot commented on Apr 30, 2018

@typescript-bot
Collaborator

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

locked and limited conversation to collaborators on Jul 31, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    QuestionAn issue which isn't directly actionable in code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @albyrock87@typescript-bot

        Issue actions

          Can't typecheck constructor in class generic parameter · Issue #23264 · microsoft/TypeScript