Proposal-temporal: Should field properties be enumerable?

Created on 24 Feb 2020  路  18Comments  路  Source: tc39/proposal-temporal

It would be nice to have e.g. Object.assign({}, Duration.from("PT42S")).seconds === 42.

behavior has-consensus

Most helpful comment

A possibility raised by a few different parties in plenary is to have a method for returning plain snapshots of the fields, e.g. toJSON (which currently serializes to string) or toObject, which would avoid language fit concerns at the expense of maximal brevity.

All 18 comments

I would be inclined to match https://tc39.es/ecma262/#sec-ecmascript-standard-built-in-objects.

That section says that built-in data properties are not enumerable "unless otherwise specified", but I'm suggesting that we _do_ specify otherwise because instances of the Temporal types are basically struct-like records very similar to objects with well-known property names and it would be convenient to preserve that similarity.

Just like the index properties of strings and arrays are enumerable, so too should be the properties of Temporal type instances that hold their structured data.

About matching existing conventions, these feel pretty similar to RegExp properties like global to me. (I believe these are non-enumerable.) Or maybe we could consider that a mistake, and try to establish new conventions?

If we go in the direction of considering objects with well-known property names to be equivalent to Temporal objects, should we go so far as to remove some of the checks that we have in the spec for the [[InitializedTemporalX]] slot? e.g. allow things like date.compare({year: 2020, month: 2, day: 27}) after all? or even Temporal.DateTime.inTimeZone.call({year: 2020, month: 2, day: 27, hour: 10, minute: 27}, 'UTC')?

It would be nice to have e.g. Object.assign({}, Duration.from("PT42S")).seconds === 42.

Note that this will not work even if we make the fields enumerable; Object.assign only takes own properties into account, and these must be on the prototype.

I don't know if it's fair to say that they _must_ be on the prototype, but that is nonetheless a good point. The above becomes much less compelling when we need to add in Object/Reflect static methods. :\

This would seem to be a good argument in favour of adding a Duration.with method; because Duration.from({...otherDuration, seconds: 42}) wouldn't work.

Meeting, Mar. 5: The intention is to make the core properties enumerable, and allow calendars to add additional enumerable properties such as era. However, this is something we should get input on when presenting at the March TC39 meeting.

Are these own data properties? I'd expect them to be accessors on the prototype, which would make their enumerability irrelevant for most use cases (object spread, Object.assign, Object.keys/entries/values, etc).

We did discuss that they would need to be own properties in order to be enumerable, but that deviates from an existing ES convention which is why we wanted input from the plenary on this.

They can be enumerable without being own, but they have to be both to be included in assign/spread.

Is this on the agenda yet?

I believe @pipobscure already put it on the agenda.

Does this still need plenary input?

I think so, yes.

it'd be great to have the notes landed so they can be easily referenced by the plenary, cc @ryzokuken

Note extracted from #487:

The Japanese calendar might choose to make .era enumerable, whereas other calendars might not. This is because for the Japanese calendar, there are 4 fields that fully define a date: era, year, month, and day. In other words, the set of fields that are enumerable should be calendar-dependent.

A possibility raised by a few different parties in plenary is to have a method for returning plain snapshots of the fields, e.g. toJSON (which currently serializes to string) or toObject, which would avoid language fit concerns at the expense of maximal brevity.

Meeting, Apr 2: Consensus is that the properties should not be own properties. Instead we will add a getFields() method, which returns a new plain JavaScript object, with all the fields as enumerable, writable, own data properties.

The code snippet from the OP would become:

Object.assign({}, Duration.from("PT42S").getFields()).seconds === 42
Was this page helpful?
0 / 5 - 0 ratings