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

Unable to do module augmentation for class constructor #19372

Closed
Alphapage opened this issue Oct 20, 2017 · 5 comments
Closed

Unable to do module augmentation for class constructor #19372

Alphapage opened this issue Oct 20, 2017 · 5 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@Alphapage
Copy link

TypeScript Version: 2.5.3

Code

// mod.d.ts
declare module 'm' {
  export class C {
    constructor(s:string,n:number)
    test(s: string): void
  }
  export function func(): void
}

// m.ts
///<reference path='./mod.d.ts'/>
import * as m from 'm'

declare module 'm' {
    interface C {
      new(d:Date): C
      constructor(d:Date): C
      (d:Date): C
      test2(): void;
      test(s:any)
    }
  }

new m.C(   // only (s:string,n:number) , no (d:Date) as expected

Expected behavior:
m.C constructor should display (s:string,n:number) and (d:Date) in intellisense
Actual behavior:
m.C constructor only displays (s:string,n:number)

You learn me how to augment a class from a module, but I'm unable to augment the class constructor.
Thank you in advance for your help.

@DanielRosenwasser DanielRosenwasser added the Question An issue which isn't directly actionable in code label Oct 20, 2017
@DanielRosenwasser
Copy link
Member

Hey there, this issue tracker isn't meant to work as a support forum. These questions tend to be better suited for StackOverflow. You may want to open a question up there instead in the future.

But the short answer is that you need to do class-to-interface decomposiotion.

@Alphapage
Copy link
Author

I'm agree with you (I think it isn't possible to achieve this that's why I posted here).
The problem is I can't change mod.d.ts file. So I can't switch to an interface to decompose the class that is why I need to augment the class constructor (I don't want to have to rewrite all the class constructors every time I only need to augment the constructor). I don't know why constructors aren't merged or added as functions are merged in my example.

For now, the only way I found is to relay on prototype like this:
new m.C(s,n) // class constructor
new m.C.prototype(d) // from interface
which is annoying (merged intellisense would be better ?)

I hope you understand my needs and you will continue to help me.

@mhegazy
Copy link
Contributor

mhegazy commented Oct 23, 2017

there is no way currently to augment a class with a new constructor signature. the interface only augments the instance side of the class and not the constructor function. a namespace can add static properties/methods but not call or construct signatures. Issue #2957 tracks that.

@Alphapage
Copy link
Author

For declaration files, class to interface decomposition would solve my problem only if every declaration files follow this rule, but as class is allowed in declaration file, then I think there should be a way to augment the class via an interface.
What I've done to achieve my goal was to add a new line to resolveAnonymousTypeMembers function in checker.ts:

if (symbol.flags & SymbolFlags.Class) {
                    const classType = getDeclaredTypeOfClassOrInterface(symbol);
                    constructSignatures = getSignaturesOfSymbol(symbol.members["__constructor"]);
                   constructSignatures.push(...getSignaturesOfSymbol(symbol.members["__new"])); // my patch

Now,

declare module 'm' {
    interface C {
      new(d:Date): C
      test2(): void;
      test(s:any)
    }
  }

augmentation will show the 2 signatures as I was expecting.
I would prefer to be able to use constructor instead of new operator because it is a class augmentation, but this is the only way I found (constructor is considered as a normal function, but new not) and it is for my personal use so no problem.

Thank you anyway for your help.

@mhegazy
Copy link
Contributor

mhegazy commented Oct 24, 2017

For declaration files, class to interface decomposition would solve my problem only if every declaration files follow this rule, but as class is allowed in declaration file, then I think there should be a way to augment the class via an interface.
What I've done to achieve my goal was to add a new line to resolveAnonymousTypeMembers function in checker.ts:

I a afraid this is the wrong approach. An interface describes the shape of the instance not the constructor. The constructor signature are part of the constructor type and not the instance.

@microsoft microsoft locked and limited conversation to collaborators Jun 14, 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

4 participants