Closed pixelzoom closed 2 years ago
The 4 Properties that this affects are identified with TODOs in the above commit.
During Thursday's TypeScript meeting, we decided to approve/resurrect StringEnumerationProperty. Thanks for catching the deprecation warnings, I'll remove them.
OK committed. Can you please review the commit, which also updates the optionize
call?
Two things:
(1) StringEnumerationProperty should allow validValues
to be optionally provided.
This is problematic:
type StringEnumerationPropertyOptions<T> = Omit<PropertyOptions<T>, 'validValues' | 'phetioType'>;
EnumerationProperty
allows validValues
to be specified because it's possible that only a subset of an enumeration may be valid. StringEnumerationProperty
should allow validValues
for the same reason. Geometric Optics has an example like this, see this.opticShapeProperty
in Optic.ts. The string union is OpticShape.ts. For a lens, 'concave' and 'convex' shapes are supported. For a mirror, 'concave', 'convex' and 'flat' are supported.
(2) Since this is a Property whose values are from a string union, should StringEnumerationProperty
be renamed to StringUnionProperty
? It would be more aligned with TypeScript terminology. And it's doubtful that this Property subclass should be used in JavaScript code.
(1) StringEnumerationProperty should allow validValues to be optionally provided.
That is currently the required first argument. The signature is constructor( values: readonly T[], value: T, providedOptions?: StringEnumerationPropertyOptions<T> ) {
. Does that seem OK? Or should we move it back to validValues
and make it a required option?
(2) Since this is a Property whose values are from a string union, should StringEnumerationProperty be renamed to StringUnionProperty? It would be more aligned with TypeScript terminology. And it's doubtful that this Property subclass should be used in JavaScript code.
To me, it behaves like an enumeration so that seems an appropriate name.
Some notes-to-self for when I look at this later:
class StringEnumerationProperty<T extends string>
so we cannot make StringEnumerationProperty<number>
const m = new StringEnumerationProperty(['x','y'])
infers the type correctly and gets the type parameter right. It may help us get rid of the as const
and typeof a[number]
pattern.
UPDATE: I found that
const x = new StringEnumerationProperty( [ 'a', 'b', 'c' ], 'a' );
type extractGeneric<Type> = Type extends StringEnumerationProperty<infer X> ? X : never;
type extracted = extractGeneric<typeof x>;
gets the type correct. But it's unclear how this could be used in practice. For instance, in GOModel.ts we need to annotate the type of raysTypeProperty
in the class attribute declaration, and cannot refer to the type from the instantiated StringEnumerationProperty at that point.
I'm inclined to request votes for (1) and (2) above at dev meeting.
5/5/2022 dev meeting: We spent considerable time discussing this (but I don't see any notes?) and decided to break into a subgroup. I think @samreid and @jonathanolson expressed interest, so assigning them.
Using the current implementation of StringEnumerationProperty, here's what I end up with in GOModel.ts (not committed). It seems a little odd to me that the string union type (RaysType
) is mentioned in the declaration, but not used in the instantiation. But maybe that's OK.
public readonly raysTypeProperty: Property<RaysType>;
...
this.raysTypeProperty = new StringEnumerationProperty( RaysTypeValues, 'marginal', {
tandem: options.tandem.createTandem( 'raysTypeProperty' )
} );
In the above commit, geometric-optics is now using StringEnumerationProperty. This will provide examples for adjusting the API/implementation of StringEnumerationProperty.
Since this is a general issue, transferring from geometric-optics to axon.
If I recall correctly, we agreed to move the required parameter into a required validValues
option. I think @jonathanolson volunteered to make the change and update occurrences.
Maybe I misunderstood. But did we have concerns about type-checking if we move the first param to validValues
option? And the inconvenience of having to use as const
for validValues
?
In Optic.ts, opticSurfaceTypeProperty
is an example of a StringEnumerationProperty that uses a subset of values from OpticSurfaceType. I experimented with replacing StringEnumerationProperty's first parameter (values
) with a required validValues
option, and discovered that as const
was not needed.
Here's a patch that makes validValues
required:
It seems to be superior to having a required first arg. Want to commit it?
But did we have concerns about type-checking if we move the first param to
validValues
option?
Type inference seems to work when specifying options.validValues
instead of just values
.
Anything else for this issue?
I applied the patch, looks good in geometric-optics.
I noticed a note in CAVQueryParameters.ts, and changed the TODO to point to this issue. Back to @samreid to decide whether to address it.
Thanks, I removed the comment. It seems this issue is ready to close. Anyone please reopen if there's more to do.
For https://github.com/phetsims/geometric-optics/issues/402, @jonathanolson added REVIEW comments to the cases where I'm creating a Property whose values are members of a string union.
For example, in GOOptions.ts:
I did not use
StringEnumerationProperty
because it was annotated as@deprecated
by @samreid.@samreid why is
StringEnumerationProperty
deprecated? It certainly looks like it's approprite to use it for TypeScript string unions.