GeezerVison is showing github.com — Allow visibility on constructors · Issue #2341 · microsoft/TypeScript
Allow visibility on constructors #2341DescriptionI think it is a pretty common pattern to have a static factory method to create a class and the constructor of this class being otherwise private so that you cannot instantiate the class unless you use the factory method. Reacted by Ilia Choly, lexigren, Javier Ros and Tega Adigu Activityqc00 commented on Mar 13, 2015 Since all "classes" are actually just functions and since there's no such thing as uncallable function, anywhere the class is visible you can also use the new operator on it.
You can however make the class non-public (e.g. in a module) and export an interface for the class. This abuses the fact that interfaces can extend classes but they're not directly instantiable nor extendable. bpasero commented on Mar 13, 2015 Well the same applies to private functions in classes, right? I don't see why we could not get a compile error for accessing a private constructor. Reacted by lexigren, Michail Klioutch, Martin Hula and Markus Ende wgebczyk commented on Mar 14, 2015 @billccn I don't like to kill requests by "JS allows then you will not be able to hide".
On thing is protect completely in TS & generated JS, other thing is to protect that to the point of generating JS. As you have explained the full protection is not possible, but having different visibility checked by compiler, should be possible.
If you don't like visibility modifiers, then use default public everywhere, there are other that find that concept useful. qc00 commented on Mar 14, 2015 Yeah, I guess if the private fields are implemented as a compiler check only, then it can probably be extended to constructors. However, the interface-based workaround already works though. dsherret commented on Mar 26, 2015 👍 There are times when I want to force the programmer to use the factory methods for code readability. The interface-based workaround creates a lot of noise in the code.
I think the compiler check only is the way to go. added this to the This milestone has been deleted milestone on May 19, 2015RyanCavanaugh commented on May 19, 2015 AbubakerB commented on Aug 5, 2015 To clarify, could a class with a private constructor be extendable?
i.e. Would this throw an error?
class A {
private constructor() {
}
}
class B extends A { // Should there be an error at A saying: "Cannot extend private class 'A'"?
}
if so, would we then allow this:
class A {
protected constructor(a?: any)
private constructor() {
}
}
class B extends A { // No error since 'A' has a non-private constructor
}wgebczyk commented on Aug 5, 2015 From non-JS developer experience that's expected behaviour. RyanCavanaugh commented on Aug 5, 2015 In the first example, B should be an error because its implicit super call is illegal. So a class with a private constructor is effectively sealed/final.
In the second example, A's declaration should be an error because all overloads of a constructor, and its implementation, must have the same visibility (same rule we have for methods). benliddicott commented on Sep 8, 2015 See also #471. Is it really required to allow constructors to be private or will protected do? z-vr commented on Jan 24, 2016 👍 can be useful for factory design pattern myitcv commented on Feb 2, 2016 Apologies if this is a repeat or just late to the party, but we are using the following pattern to achieve private constructors:
interface ExampleBuilder {
Instance(): Example;
}
export interface Example {
Val(): number;
}
export let Example: ExampleBuilder = class ExampleImpl {
constructor(v: number) {
}
Val(): number {
return 42;
}
static Instance(): Example {
return new ExampleImpl(2);
}
};
let x = Example.Instance(); // OK: x has type Example
let y = new Example(5); // ERROR: Cannot use 'new' with an expression whose type lacks a call or construct signature.
Note this can be tidied up even more using the recently merged readonly modifier. dsherret commented on Feb 2, 2016 Paul Jolly (@myitcv) that's pretty cool to enforce it for now... probably the best way mentioned in my opinion. It's still too verbose though and takes a few seconds to understand what's going on, which is why an access modifier would still be very nice on constructors.
Personally, I'm just marking all my future private constructors with // todo: make private once supported comments and not calling the constructors. It will be nice once this feature comes in order to get some enforcement and better documentation with an access modifier. myitcv commented on Feb 2, 2016 David Sherret (@dsherret)
It's still too verbose though and takes a few seconds to understand what's going on
Agreed. We don't suffer too much from that cognitive load because these classes are code generated. So the interface to the programmer is actually nice and simple. mhegazy commented on Feb 17, 2016 agaace commented on Jun 21, 2016 Hi, is this feature going to be released in some future version of typescript?
As of now, trying to declare a private or protected constructor gives me this error in typescript 1.8.10:
error TS1089: 'private' modifier cannot appear on a constructor declaration.
Ahh, nevermind. Just found out the road map that states this feature will be included in typescript 2.0. kitsonk commented on Jun 22, 2016
Ahh, nevermind. Just found out the road map that states this feature will be included in typescript 2.0.
Also the milestone being set to TypeScript 2.0 and the label Fixed would indicate that it is included. Anything with a label of Fixed generally is included in master and available via npm install typescript@next. stephenmartindale commented on Sep 22, 2016 I am using TypeScript 2.0.2 RC and still get TS1089 when I try to make a private constructor. Am I doing it wrong or is this simply not fixed? mhegazy commented on Sep 22, 2016
I am using TypeScript 2.0.2 RC and still get TS1089 when I try to make a private constructor. Am I doing it wrong or is this simply not fixed?
it is working for me. make sure your command alias is pointing to the right version, and that your editor is updated to use the latest TS version. Reacted by Stephen Martindale stephenmartindale commented on Sep 22, 2016 I found the problem. It was the fault of gulp-typescript which was using the wrong version of tsc despite my specifications in package.json and what was resolved on the PATH.
For anyone else having this problem, my solution was to edit my gulpfile.js and...
require TypeScript before gulp-typescript as follows:
// Tool-Chain: Scripts
var tsc = require("typescript");
var typescript = require('gulp-typescript');
- Provide the compiler as an override when defining my build task:
// Task(s): Build TypeScript Outputs
var tsconfig = typescript.createProject("path to tsconfig", { typescript: tsc });
gulp.task('build:scripts', function () {
let ts = tsconfig.src()
.pipe(sourcemaps.init())
.pipe(typescript(tsconfig));
return ts.js.pipe(sourcemaps.write(".")).pipe(gulp.dest(path.join(outputs.root, outputs.scripts)))
});
Reacted by Ryan Cavanaugh
MetadataMetadataDevelopmentNo branches or pull requestsIssue actions
|