Skip to content

Interfaces that define a no-arg constructor require implementing classes to implement a constructor, even when one is not necessary and the default would suffice #33859

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
EdwardDrapkin opened this issue Oct 7, 2019 · 2 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@EdwardDrapkin
Copy link

TypeScript Version: 3.6.3 and 3.7-beta

Search Terms:
constructor
default
no args

Code

interface JustAnEmptyConstructor {
    constructor(): this;
}

interface JustAnEmptyConstructor2 {
    constructor(): JustAnEmptyConstructor2;
}

class WillError implements JustAnEmptyConstructor {

}


class WillError2 implements JustAnEmptyConstructor2 {

}

Expected behavior:
class WillError should be able to successfully implement the constructor required by the interface without explicitly defining one. It errors whether the required constructor is typed as constructor(): this or constructor(): JustAnEmptyConstructor

Actual behavior:

TS errors:

Class 'WillError' incorrectly implements interface 'JustAnEmptyConstructor'.
  Types of property 'constructor' are incompatible.
    Type 'Function' is not assignable to type '() => this'.
      Type 'Function' provides no match for the signature '(): this'.(2420)

It appears that the implicit, default constructor is typed as Function instead of (): this.

Playground Link

Related Issues:
This may be related, may not be: #29707

@jcalz
Copy link
Contributor

jcalz commented Oct 7, 2019

I think this is related to #31020 and #3841 and #5989.

The constructor inside a class definition does not really correspond to a method named constructor on the class's instance type. So even if you implement the constructor explicitly you'll still get the same error. The only way not to get an error is to add a phantom type-system-only property named constructor of a type that conforms. Maybe you can even salvage a little type safety if you're clever about the typing:

class Okay implements JustAnEmptyConstructor {
    ["constructor"]!: (...a: ConstructorParameters<typeof Okay>) => this
}

class Okay2 implements JustAnEmptyConstructor2 {
    ["constructor"]!: (...a: ConstructorParameters<typeof Okay2>) => this
}

class WillError implements JustAnEmptyConstructor {
    ["constructor"]!: (...a: ConstructorParameters<typeof WillError>) => this
//  ~~~~~~~~~~~~~~~ <-- error!
    constructor(x: string) {

    }
}

Playground link

But I'd stay away from this sort of thing if I were you.

@RyanCavanaugh RyanCavanaugh added the Question An issue which isn't directly actionable in code label Oct 17, 2019
@typescript-bot
Copy link
Collaborator

This issue has been marked as 'Question' and has seen no recent activity. It has been automatically closed for house-keeping purposes. If you're still waiting on a response, questions are usually better suited to stackoverflow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

4 participants