Closed pixelzoom closed 2 years ago
I just ran into an example case of this. I had this code in AmplitudeModulatorDemoNode.js
// LFO enabled control
const lfoEnabled = new Checkbox(
new Text( 'LFO Enabled', { font: LABEL_FONT } ),
amplitudeModulatorDemo.amplitudeModulator.enabledProperty,
{ boxWidth: 16 }
);
The enabledProperty
on the modulator is present because it extends EnabledComponent
, and the type for it is IProperty<boolean>
. When I changed AmplitudeModulatorDemoNode
to TypeScript, my IDE was complaining that the type for the enabledProperty
was incorrect, so I ended up adding as BooleanProperty
like this:
// LFO enabled control
const lfoEnabled = new Checkbox(
new Text( 'LFO Enabled', { font: LABEL_FONT } ),
amplitudeModulatorDemo.amplitudeModulator.enabledProperty as BooleanProperty,
{ boxWidth: 16 }
);
This works in the sense that the TS compiler is okay with it, but it seems to me like we're working around the type system rather than working with it.
This proposal introduces LinkableElement
and demonstrates how it can address cases like the one the preceding comment:
Re https://github.com/phetsims/axon/issues/382#issuecomment-1081154975 ...
I'm not excited about having to do IProperty<boolean> & LinkableElement
wherever some part of the implementation (often in a superclass, far from where I'm adding LinkableElement) needs to call addLinkedElement
. But maybe that's what we're stuck with, give the Property/TinyProperty "problem".
When we discover some other aspect of PhetioObject that's needed for IProperty/IReadonlyProperty, will we add yet another type that we'll need to patch in like LinkableElement
?
Thanks, I agree fully. Here is a better proposal:
This adds the LinkedElement API to IReadOnlyProperty, and TinyProperty implements get phetioFeatured
as a constant false, like it already does for isPhetioInstrumented
.
I applied the above patch and reviewed. That looks like a readable way to address the needs of addLinkedElement
.
I applied the patch from above. Not sure if this issue should be closed or left open for further discussion or PSA.
We probably need an issue (or issues?) to go back and change all the places where we were previously forced to use Property, and use IProperty or IReadOnlyProperty as appropriate.
For example, I'm going to clean up Geometric Optics in this issue: https://github.com/phetsims/geometric-optics/issues/416. But there are definitely cases in sun/scenery-phet/joist that need to be revised.
In the above commit, I attempted to replace Property
with IProperty
where appropriate in sun and scenery-phet APIs.
@samreid There's still something missing from the LinkableElement
API -- access to tandem
.
General example:
class MyClass extends PhetioObject {
constructor( myProperty: IProperty<boolean>, ... ) {
...
this.addLinkedElement( myProperty, {
tandem: options.tandem.createTandem( myProperty.tandem.name )
} );
}
}
myProperty
if flagged with TS2339: Property 'tandem' does not exist on type 'IProperty<boolean>'
.
Getting the tandem name from the element is a very common pattern that I've used everywhere. It ensures that the tandem name used for the link is the same as the element. And it's essential when there are multiple instances of MyClass, with diffferent tandem names for myProperty
.
Thanks, I committed a proposed fix. Can you please review?
Looks good, thanks.
I think the only thing left to do here is https://github.com/phetsims/axon/issues/382#issuecomment-1086037626.
Thanks, it seems the next step for https://github.com/phetsims/axon/issues/382#issuecomment-1086037626 is discussion in dev meeting.
... and go back and correct places where IProperty or IReadOnlyProperty should have been used?
We discussed this as a whole dev team today. We are having trouble as the Property interface intersects with PhET-iO.
On one hand, if we have a Checkbox, PhET devs should pass a Property
in there to decrease technical debt when we convert to PhET-iO (because it will have to be an instrumented Property). But that cascades all the way through to the model, and isn't necessarily that helpful to exclude TinyProperty at every stage of things. Also for any dev using Checkbox (an open source component of an open source library) who doesn't care about PhET-iO, TinyProperty should work just fine.
We will discuss this further next week.
Today we agreed to remove
// isPhetioInstrumented(): boolean;
// get phetioFeatured(): boolean;
// get tandem(): Tandem;
from IReadOnlyProperty and to rename AbstractProperty => ReadOnlyProperty. Sun components will use Property instead of IProperty. We will use instanceof
checks where necessary in Node, etc. I'll take the lead.
I made it very far on the recommendations from today, but ran into roadblocks from DynamicProperty. Rather than abandon the work, I decided to commit and add ts-ignores. @jonathanolson can you please search the codebase for https://github.com/phetsims/axon/issues/382
to see the remaining problems, two of which are in density?
In https://github.com/phetsims/density-buoyancy-common/issues/74 we established LinkableProperty which will work well here.
I was able to address the remaining ts-ignore. I think this issue can be closed.
Slack discussion:
Chris Malley 11:59 AM As I’m doing these conversions, it makes me sad that I have to type parameters as Property instead of IProperty because some ancestor class calls addLinkedElement and therefore requires a PhetioObject. Typing as Property provides access to things that should not be used, like reset .
Michael Kauzmann:palm_tree: 1:07 PM I feel like all scenery-phet and sun components should only take a Property (or an interface based on it). I wouldn't think it ideal to have 10 components that don't yet have a LinkedElement because they aren't PhET-iO instrumented, but they take an IProperty and in a couple months have usages that pass it a TinyProperty. They should be Properties for iO support at this time.
Chris Malley 2:00 PM Why should they be Property (and expose the entire Property API, including reset ) simply because they need to be passed to addLinkedElement?
Sam Reid 2:13 PM What about specifying the minimal interface used?
2:14 Or, to avoid repeating ourselves:
Chris Malley 2:18 PM I think this is a problem with
IReadOnlyProperty
. It omits the PhetioObject-ness of read-only Properties. 2:22 As far as I can telladdLinkedElement
doesn’t required anything about its “element” to be mutable. But it’s loaded with dependencies on PhetioObject. Can some part of PhetioObject be factored out as IReadOnlyPhetioObject ? And then type IReadOnlyProperty = { … } & IReadOnlyPhetioObject;Sam Reid 2:29 PM Here’s all we need to know about linked elements:
2:29 Then the signature can read: