Repository navigation
Suggestion: static constructors #265
Description
A static constructor is a function that is run only once when the class is loaded. It can be used to initialize static class members and maybe as entry point to the application.
Suggested syntax is:
class MyClass {
static initialized = false;
static constructor() {
MyClass.initialized = true;
}
}
alert(MyClass.initialized);That would be same as the following:
class MyClass {
static initialized = false;
static __ctor = (() => {
MyClass.initialized = true;
})();
}
alert(MyClass.initialized);Except that __ctor does not need to be assigned to the class in the output code, and only needs to be invoked in an anonymous function. Also compiler can check that no more than one static constructor is defined in a class.
Update: Since this generates an Immediately-Invoked Function Expression (IIFE), compiler should make sure to move it to the end of the class definition in the output JavaScript.
TypeScript:
class MyClass {
static constructor() {
MyClass.initialized = true;
}
static initialized = false;
}Expected JavaScript output:
var MyClass = (function () {
function MyClass() {
}
MyClass.initialized = false;
// run last
(function () {
MyClass.initialized = true;
})();
return MyClass;
})();Note that body of the static constructor is moved to the bottom and invoked.
Related suggestion in codeplex: Please add static constructors to classes
Activity
basarat commentedon Jul 27, 2014
👍
ahejlsberg commentedon Jul 27, 2014
You can already accomplish this with a merged class/module:
Or, for that matter, you can just have the call to initialize immediately follow the class declaration:
omidkrad commentedon Jul 27, 2014
Pleasure hearing from Mr. Hejlsberg...
The only limitation I see there is that you can't make it private, whereas in my example you can :)
knazeri commentedon Jul 27, 2014
👍 for class/module merge suggestion
NoelAbrahams commentedon Jul 27, 2014
The merged class/module code requires that the developer remember to call
MyClass.initialise().The suggestion I believe is that given the following:
We get JavaScript
omidkrad commentedon Jul 27, 2014
Noel Abrahams (@NoelAbrahams) Yes, good point about having to remember to call it in the merged class/module pattern.
However, Anders Hejlsberg (@ahejlsberg)'s code has the benefit that call to the static method is made at the very end when the class is completely loaded. I updated the suggestion above to reflect that. The static constructor syntax should only generate an anonymous function invocation at the end of the JavaScript class output.
DanielRosenwasser commentedon Jul 27, 2014
Privacy is a good point here, but it's worth pointing out that you can be a little "evil" to achieve the same goal without having to modify the language. ;)
You can even replace
C.initialize = undefinedwithdelete C.initializeif you're afraid someone will iterate over your class in afor..ofloop.But yes, here the user is still responsible with calling
initialize.omidkrad commentedon Jul 27, 2014
The suggested static constructor syntax remains to be superior IMO and has best of everything: 😌
RyanCavanaugh commentedon Jul 28, 2014
Closing as Too Complex - we would need a more compelling use case since
modulemerging provides a very close approximation to the desired behavior.8 remaining items
danquirk commentedon May 27, 2015
nin-jin (@nin-jin) You can use
thisinstaticmember functions and accessors, just not member initializers.Note that in any comparison to other languages you need to consider the somewhat unique constraints TypeScript operates with (as a superset of JavaScript and emitting clean, idiomatic JavaScript with minimal or no strange rewriting). Were we designing in a green field with only our own thoughts the language would look very different :)
felixfbecker commentedon May 12, 2016
But what about inheritance?
I would expect called to be logged twice.
PascalSenn commentedon Jun 14, 2016
Felix Becker (@felixfbecker) Every static property is bind to the class. It cannot be inherited. So the static constructor should also follow this pattern to ensure a equal behavior.
felixfbecker commentedon Jun 14, 2016
PascalSenn static properties are inherited in ES6 and TypeScript.
PascalSenn commentedon Jun 14, 2016
Felix Becker (@felixfbecker) Thats new for me. Didnt know that. C# doesnt support it, so i thought Typescript neither.
felixfbecker commentedon Jun 14, 2016
PascalSenn you can even do it in ES5:
mark-norgate commentedon Sep 14, 2016
Ryan Cavanaugh (@RyanCavanaugh) I don't think the merged module solution is anywhere near an approximation to a static constructor. It is still required that you call the static member whether you use merged modules or not. A static constructor would initialise automatically.
rjamesnw commentedon Apr 28, 2017
It's too bad generic type references were dropped in static functions. I was using some static constructor style methods on some classes (similar to JoshMcCullough's post above) and now it's all broken. The only workaround was to convert the private static constructor methods to private instance methods and call them instead via the prototype from another static constructor method (or directly after the class). I didn't want to duplicate my class generic signature on my static method as well, that's just getting too silly.
Alphapage commentedon Sep 30, 2017
Hello,
I hope Typescript will implement static constructors like this:
sirisian/ecmascript-static-constructor#1
It would solve "function properties" typing problem too: https://stackoverflow.com/questions/12766528/build-a-function-object-with-properties-in-typescript
rjamesnw commentedon Oct 27, 2017
Alphapage (@Alphapage) TypeScript supports many coming ES6+ changes today, best it can, and targeting such code will output code like this
class MyClass { }- which works in non-IE browsers. ;) However, what you are suggesting - to support an invokable 'MyClass()' constructor - is an error since, currently, ES6 introduces a new non-invokable function type (for classes). The minute someone targets ES6+, their code would fail. ;) The spec would need to be changed regarding non-callable class functions in upcoming approval stages at some ECMAScript proposal level before this was even considered.BTW: There's already a proposal here as well: https://github.com/tc39/ecma262/blob/master/workingdocs/callconstructor.md
gmurray81 commentedon Jan 27, 2018
I'm not sure of the exact mechanics of some of the tree shakers out there, but won't some of these strategies disrupt the tree shakers? Calling a static method on the Type as a separate action outside of the class's IIFE (in ES5) may be seen as a reference to the type? Or containing some side effect that may not be possible to omit? Presumably being able to wrap some code inside of the class's ES5 iffe would been seen as more atomic with the definition of the type?
nin-jin commentedon Jan 27, 2018
gmurray81 tree shaking is partial workaround of autoloaders absence. Better to use bundler that supports autoloading. MAM in example.
gmurray81 commentedon Jan 27, 2018
nin-jin (@nin-jin) even if you could just persuade everyone to use different technology in their projects to avoid a problem (some of us need to write library code for others to consume) there would still be an argument that it should be easy to make the creation/calling of the static cons atomic with the class creation.
It seems like shoving an IIFE on the last defined static property of a type, as suggested above, might be the closest you can come with the syntax as it stands. It's a little ugly, though, comparatively.
Misaka-0x447f commentedon Feb 14, 2018
Aymeric Beaumet (@aymericbeaumet) The solution you provided may caused inspector report a 'unused variable' warning which cannot be silenced in webstorm... (I cannot write better one until now. Thinking.)