You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
new myVariable.constructor() doesn't compile #4356
The compiler will still emit code in the presence of errors unless given the --noEmitOnError flag. Emit in the face of syntactic errors is a best-effort emit with no guarantees in syntactic validity.
I appreciate the --noEmitOnError flag when doing development, but this doesn't help when our CI blocks deploy when there's a compile error, and there's no option to disable errors on lines (a la tslint).
I strongly object to the By Design tag here, since a better design would be to avoid triggering a compile error at all. The posted workaround is unnecessarily verbose.
The constructor property will only be correct if the constructor function chooses to initialize it. Although TypeScript generates code to do so, it is not a requirement and you can't generally rely on it for an arbitrary constructor function (e.g. one implemented in a JavaScript framework). For that reason TypeScript doesn't strongly type the constructor property.
@jiaweihli but all that says is that the actual field Object.prototype.constructor points to Object. It doesn't imply anything about whether or not new'd values automatically get a constructor property.
Ryan Cavanaugh (@RyanCavanaugh) I believe the spec is a bit unclear here - it says the field Object.prototype.constructor points to %Object%, which I think refers to the constructor, since it's subclassable.
This has been the stance of MDN since the earliest version of that page, so that's most likely their interpretation of the ES1 spec. The relevant section begins on page 73 here.
I don't necessarily have the knowledge needed to resolve this ambiguity, but I think it's worth looking into this since a lot of freely available documentation lists the behavior I mentioned above. Anecdotally, the code has worked for me in several different environments, and is also supported by all major browsers.
I get that this works in many runtimes, but I'm still not seeing it being spec'd behavior. Why does the fact that Object.prototype.constructor === Object mean that a.constructor === A ?
Correct me if I am wrong, but doesn't %Object% refer to the intrinsic value of the current realm, ergo the current execution context, therefore a.constructor === A:
19.1.3.1 Object.prototype.constructor
The initial value of Object.prototype.constructor is the intrinsic object %Object%.
And intrinsic objects are described as:
Within this specification a reference such as %name% means the intrinsic object, associated with the current Realm, corresponding to the name.
I think you can strongly type constructor for ES6 classes. The constructor property is added to the C.prototype in ClassDefinitionEvaluation step 18. It is configurable, though, so users could presumably delete it (GeneratorFunction instances, notably, do not have a constructor property on their [[prototype]] for reasons users might also find compelling - not leaking a reference to the constructor when vending instances IIUC).
People above are also correct that Object.prototype has a constructor property that points to Object (and thus any object with Object.prototype in its prototype chain and no other constructor properties will have a .constructor property pointing to Object). But I don't think this has any bearing on whether you can strongly type the .constructor property of class instances.
Activity
DanielRosenwasser commentedon Aug 19, 2015
The compiler will still emit code in the presence of errors unless given the
--noEmitOnErrorflag. Emit in the face of syntactic errors is a best-effort emit with no guarantees in syntactic validity.jklmli commentedon Aug 19, 2015
This code should be supported on all browsers, given https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor.
I appreciate the
--noEmitOnErrorflag when doing development, but this doesn't help when our CI blocks deploy when there's a compile error, and there's no option to disable errors on lines (a la tslint).I strongly object to the
By Designtag here, since a better design would be to avoid triggering a compile error at all. The posted workaround is unnecessarily verbose.[-]`new myVariable.constructor()` doesn't work[/-][+]`new myVariable.constructor()` doesn't compile[/+]DanielRosenwasser commentedon Aug 19, 2015
I apologize, I misread the original issue. I thought you were suggesting that the code should not have been emitted at all.
ahejlsberg commentedon Aug 20, 2015
The
constructorproperty will only be correct if the constructor function chooses to initialize it. Although TypeScript generates code to do so, it is not a requirement and you can't generally rely on it for an arbitrary constructor function (e.g. one implemented in a JavaScript framework). For that reason TypeScript doesn't strongly type theconstructorproperty.RyanCavanaugh commentedon Aug 21, 2015
I can't find any evidence supporting this. All runtimes seem to hook this up automatically.
I can't find any evidence supporting this, either. The ES spec doesn't define that this property is present as a result of object creation.
http://www.ecma-international.org/ecma-262/6.0/#sec-evaluatenew
http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects-construct-argumentslist-newtarget
http://www.ecma-international.org/ecma-262/6.0/#sec-objectcreate
jklmli commentedon Aug 24, 2015
MDN lists the relevant specs near the bottom of the page - this is the most relevant:
http://www.ecma-international.org/ecma-262/6.0/#sec-object.prototype.constructor
RyanCavanaugh commentedon Aug 25, 2015
@jiaweihli but all that says is that the actual field
Object.prototype.constructorpoints toObject. It doesn't imply anything about whether or notnew'd values automatically get aconstructorproperty.jklmli commentedon Aug 26, 2015
Ryan Cavanaugh (@RyanCavanaugh) I believe the spec is a bit unclear here - it says the field
Object.prototype.constructorpoints to%Object%, which I think refers to the constructor, since it's subclassable.This has been the stance of MDN since the earliest version of that page, so that's most likely their interpretation of the ES1 spec. The relevant section begins on page 73 here.
I don't necessarily have the knowledge needed to resolve this ambiguity, but I think it's worth looking into this since a lot of freely available documentation lists the behavior I mentioned above. Anecdotally, the code has worked for me in several different environments, and is also supported by all major browsers.
kitsonk commentedon Aug 26, 2015
@jiaweihli appears to be right. Given the following in Chrome 44:
a.constructorreferencesAand works as expected.RyanCavanaugh commentedon Aug 26, 2015
I get that this works in many runtimes, but I'm still not seeing it being spec'd behavior. Why does the fact that
Object.prototype.constructor === Objectmean thata.constructor === A?kitsonk commentedon Aug 27, 2015
Correct me if I am wrong, but doesn't
%Object%refer to the intrinsic value of the current realm, ergo the current execution context, thereforea.constructor === A:And intrinsic objects are described as:
mhegazy commentedon Aug 27, 2015
Pinging Brian Terlson (@bterlson) for this one.
bterlson commentedon Aug 28, 2015
I think you can strongly type constructor for ES6 classes. The constructor property is added to the
C.prototypein ClassDefinitionEvaluation step 18. It is configurable, though, so users could presumably delete it (GeneratorFunction instances, notably, do not have a constructor property on their [[prototype]] for reasons users might also find compelling - not leaking a reference to the constructor when vending instances IIUC).People above are also correct that Object.prototype has a constructor property that points to Object (and thus any object with Object.prototype in its prototype chain and no other constructor properties will have a .constructor property pointing to Object). But I don't think this has any bearing on whether you can strongly type the .constructor property of class instances.
RyanCavanaugh commentedon Sep 28, 2015
Duplicate of #3841
RyanCavanaugh commentedon Mar 7, 2016
Reopening since #3841 is for the static side whereas this is for the instance side
RyanCavanaugh commentedon Jun 23, 2021
Let's track at #4586