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
In recent days it has become apparent that we need to give more thought to the question of what qualifies as a record field. It's absolutely clear that {email: '[email protected]'} has an email field, but does it have a toString field? This is not so easy to answer.
I see four possibilities, as shown in the table below:
+----------------------------+-----------+-----------+
| property location | own | proto |
+----------------------------+-----+-----+-----+-----+
| enumerable? | y | n | y | n |
+----------------------------+-----+-----+-----+-----+
| Object.keys | x | | | |
| Object.getOwnPropertyNames | x | x | | |
| getEnumerablePropertyNames | x | | x | |
| prop in o | x | x | x | x |
+----------------------------+-----------+-----------+
Here's the script which generates the table:
'use strict';functionO(){}O.prototype.enumerablePrototypeProperty='enumerablePrototypeProperty';Object.defineProperty(O.prototype,'nonEnumerablePrototypeProperty',{configurable: false,enumerable: false,writable: false,value: 'nonEnumerablePrototypeProperty',});consto=newO();o.enumerableOwnProperty='enumerableOwnProperty';Object.defineProperty(o,'nonEnumerableOwnProperty',{configurable: false,enumerable: false,writable: false,value: 'nonEnumerableOwnProperty',});const_includes=Array.prototype.includes;process.stdout.write('+----------------------------+-----------+-----------+\n'+'| property location | own | proto |\n'+'+----------------------------+-----+-----+-----+-----+\n'+'| enumerable? | y | n | y | n |\n'+'+----------------------------+-----+-----+-----+-----+\n'+'| Object.keys |'+test(_includes.bind(Object.keys(o)))+'\n'+'| Object.getOwnPropertyNames |'+test(_includes.bind(Object.getOwnPropertyNames(o)))+'\n'+'| getEnumerablePropertyNames |'+test(_includes.bind(getEnumerablePropertyNames(o)))+'\n'+'| prop in o |'+test(prop=>propino)+'\n'+'+----------------------------+-----------+-----------+\n');functiongetEnumerablePropertyNames(o){constprops=[];for(constpropino)props.push(prop);returnprops;}functiontest(pred){return['enumerableOwnProperty','nonEnumerableOwnProperty','enumerablePrototypeProperty','nonEnumerablePrototypeProperty',].map(prop=>' '+(pred(prop) ? 'x' : ' ')+' |').join('');}
We must choose from these four definitions:
A field is a property.
A field is an own property.
A field is an enumerable property.
A field is an enumerable own property.
We should consider "strict" record types (#128) before making a choice.
@Avaq and I have discussed the possibility of strict records having a different definition of field from the one chosen for regular records. This is potentially problematic. Imagine we were to decide that a field is an enumerable property, and that we proceeded to write the following:
line is member of LineType because it has all the required enumerable properties, each with a suitable value.
Imagine that for strict records we decided that a field is an own enumerable property. This would mean that line is not a member of the strict equivalent of LineType because it lacks a dy field.
If possible, we should use the same definition of field for both regular and strict records so a member of a record type is only excluded from the equivalent strict record type for having additional fields.
I don't think it's possible to list all of an object's properties regardless of where and how they are defined (please correct me if I'm wrong). As a result, prop in o cannot be used to define strict record types as we would need to test an infinite number of possible property names to ensure that no unwanted fields are present. For consistency, we should avoid it for regular record types as well.
This leaves three definitions:
A field is an own property.
A field is an enumerable property.
A field is an enumerable own property.
It would be a shame not to support prototypal inheritance, as I consider it one of the good parts of JavaScript. I suggest we state that a field is an enumerable property. Note that this means that Promise.resolve(42) is not a member of $.RecordType({then: $.AnyFunction}) as @JAForbes requested in #141. I can live with this. One could define an equivalent type via $.NullaryType (or even $.UnaryType).
The text was updated successfully, but these errors were encountered:
In recent days it has become apparent that we need to give more thought to the question of what qualifies as a record field. It's absolutely clear that
{email: '[email protected]'}
has anemail
field, but does it have atoString
field? This is not so easy to answer.I see four possibilities, as shown in the table below:
Here's the script which generates the table:
We must choose from these four definitions:
We should consider "strict" record types (#128) before making a choice.
@Avaq and I have discussed the possibility of strict records having a different definition of field from the one chosen for regular records. This is potentially problematic. Imagine we were to decide that a field is an enumerable property, and that we proceeded to write the following:
line
is member ofLineType
because it has all the required enumerable properties, each with a suitable value.Imagine that for strict records we decided that a field is an own enumerable property. This would mean that
line
is not a member of the strict equivalent ofLineType
because it lacks ady
field.If possible, we should use the same definition of field for both regular and strict records so a member of a record type is only excluded from the equivalent strict record type for having additional fields.
I don't think it's possible to list all of an object's properties regardless of where and how they are defined (please correct me if I'm wrong). As a result,
prop in o
cannot be used to define strict record types as we would need to test an infinite number of possible property names to ensure that no unwanted fields are present. For consistency, we should avoid it for regular record types as well.This leaves three definitions:
It would be a shame not to support prototypal inheritance, as I consider it one of the good parts of JavaScript. I suggest we state that a field is an enumerable property. Note that this means that
Promise.resolve(42)
is not a member of$.RecordType({then: $.AnyFunction})
as @JAForbes requested in #141. I can live with this. One could define an equivalent type via$.NullaryType
(or even$.UnaryType
).The text was updated successfully, but these errors were encountered: