ColinEberhardt / assemblyscript-temporal

An implementation of TC39 temporal for AssemblyScript
24 stars 6 forks source link

Call for feedback on API design #20

Closed ColinEberhardt closed 3 years ago

ColinEberhardt commented 3 years ago

Based on the current implementation progress, the PlainDate and PlainDateTime types are now relatively complete. These should be useful for anyone wanting to perform non-timezone aware date and time manipulation.

Before making a v1.0 release I am keen to stabilise the API. The biggest challenge here is dealing with union types. For example, the first arg of the PlainDate.add method unions three different types:

add(durationLike: Temporal.Duration | DurationLike | string, options?: ArithmeticOptions);

This allowing you to do the following:

const date = new PlainDate(...);
// add one day, three different ways
date.add(new Duration(0, 0, 0, 1));
date.add("1D");
date.add({ days: 1 });

Unfortunately AssemblyScript doesn't support union types so we need to use a different technique here.

There are a few options this library could employ:

1. Static Type Checks

Use a generic type then perform static type checks to determine the type.

Unfortunately the compiler requires type information, which must be provided as follows:

const date = new PlainDate(...);
// add one day, three different ways
date.add<Duration>(new Duration(0, 0, 0, 1));
date.add<string>("1D");
date.add<DurationLike>({ days: 1 });

2. Create multiple API methods

This method could be split into three, with the one that is considered the most frequently used given the plain add form:

const date = new PlainDate(...);
// add one day, three different ways
date.add({ days: 1 });
date.addDuration(new Duration(0, 0, 0, 1));
date.addString("1D");

What do people prefer? Any other ideas?

dcodeIO commented 3 years ago

One thought: When using Static Type Checks, the type can also be omitted / inferred. For example, the following two lines should work without explicitly specifying the type:

date.add(new Duration(0, 0, 0, 1));
date.add("1D");

when add is add<T>(value: T) while

date.add<DateLike>({ days: 1 });

would require implementing my suggestion in https://github.com/ColinEberhardt/assemblyscript-temporal/issues/2#issuecomment-791388606, so

date.add({ days: 1 });

which cannot be inferred, would fall back to T = DateLike, in turn allowing to omit the type.

ColinEberhardt commented 3 years ago

Ah, I misunderstood your earlier comment. In which case option 1 becomes:

const date = new PlainDate(...);
// add one day, three different ways
date.add(new Duration(0, 0, 0, 1));
date.add("1D");
date.add<DurationLike>({ days: 1 });

Thats not a bad option. However, the DurationLike version of the method is probably the most popular!

ColinEberhardt commented 3 years ago

@dcodeIO how likely is it that you would implement type parameter defaults?

dcodeIO commented 3 years ago

I see a need for it, and seems unproblematic (haven't investigated in detail, though), so I'd say it's likely. Just can't say when :)

ColinEberhardt commented 3 years ago

Just can't say when :)

I'm happy to play the long game - in which case option (1) is the clear winner :-)