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

Provide a way for static method redeclaration #7597

Closed
iby opened this issue Mar 20, 2016 · 3 comments
Closed

Provide a way for static method redeclaration #7597

iby opened this issue Mar 20, 2016 · 3 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@iby
Copy link

iby commented Mar 20, 2016

I searched issues and SO, this seems to be something that comes up often, but there's no definitive / any answer to this. I have a proposal.

abstract class Foo {
    public static construct(...args:any[]):Foo {
        return new (<any>this)(...args);
    }
}

class Bar extends Foo {
    protected x:any;
    public constructor(x?:any) {
        super();
        this.x = x;
    }
}

console.log(Bar.construct(1)); // Bar { x: 1 }

In Bar I want to define the same constructor signature for the static construct method. I've tried several things without much success:

  • Interfaces are not an option, explained clearly in Introduce a way to enforce a static contract #1263.
  • Could potentially have an intermediary abstract class with all declarations, but static cannot be abstract. Reasonable.
  • Definition merging sounded promising, but class merging is not allowed. Yet?
  • Override the actual method with an actual implementation – this is not really an answer, it results in too much code that does absolutely nothing.

There's one solution that partially works. Partially, because it gives JetBrains IDE the necessary hinting, that's all I want for now. Besides that it's useless.

declare class Baz extends Foo {
    public static instance(y?:any):Baz;
}

class Baz extends Foo {
    protected y:any;
    public constructor(y?:any) {
        super();
        this.y = y;
    }
}

This fails to compile with Duplicate identifier 'Baz' error. If the ambient declaration moved somewhere else, so that typescript doesn't compile it, then the IDE gets the hinting and tsc doesn't fail. But couldn't that just work like in example above? The rationale is:

  • Ambient declarations don't do much besides type checking and hinting.
  • Can be injected into final declarations produced by compiler.
  • Final declarations are fully reusable.
@mhegazy
Copy link
Contributor

mhegazy commented Mar 28, 2016

looks like a duplicate of #5863.

i think the original example would have been declared as:

abstract class Foo {
    public static construct(...args:any[]): this {
      ....
    }
}

@mhegazy
Copy link
Contributor

mhegazy commented Mar 28, 2016

Definition merging sounded promising, but class merging is not allowed. Yet?

A class introduces an instance type in the "type" space and a constructor function in the "value" space. interface + class merging augments the instance space, namespace + class merging augments the value space.

class Bar extends Foo {
    public x: any;
    public constructor(x?: any) {
        super();
        this.x = x;
    }
}

declare namespace Bar {
    function construct(x?: any): Bar;
}

Bar.construct().x // ok

@mhegazy mhegazy closed this as completed Mar 28, 2016
@mhegazy mhegazy added the Question An issue which isn't directly actionable in code label Mar 28, 2016
@iby
Copy link
Author

iby commented Mar 28, 2016

Nice! Some ides don't pick this up, but that seems to work well. Thanks for a detailed example.

@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

2 participants