-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Should optionize
2nd argument really default to {}
?
#105
Comments
It is buggy for the second arg to be the same as the first if there are any parent optional options. If that is the case, then by defaulting the self options to the providedOptions, it will require you to fill in defaults for all optional options from your parents as well. Since the majority of cases in the project will occur in subtypes with parent options, I'm hesitant to make this change. Does that make sense? Did I understand the question correctly? I think there is a good chance that this issue is going to relate heavily to what @samreid said in https://github.com/phetsims/phet-io/issues/1843#issuecomment-1049479690, Happy to talk it out too. |
I don't follow how that it relevant to this use case. |
Here's an example in GO LensShapes.ts: type LensShapesOptions = {
isHollywooded?: boolean,
offsetRadius?: number
};
class LensShapes implements OpticShapes {
...
constructor( ..., providedOptions?: LensShapesOptions ) {
...
const options = optionize<LensShapesOptions, LensShapesOptions>( {
isHollywooded: true
offsetRadius: 100
}, providedOptions ); There is no superclass involved. All that I'm doing is filling in default values for a couple of optional options that are specific to this class. Why is it necessary to specify |
I don't mean the 3rd arg, which we don't need to discuss in this part, I mean when any options from the parent are part of the providedOptions type. RE your code in #105 (comment): Yes, exactly. You gave the perfect example of the side where self options could default to providedOptions. Here is the spot where it could be confusing: import optionize from '../phet-core/js/optionize.js';
class OpticShapes {}
type OpticShapesOptions = {
superOption1?: number,
superOption2?: number,
superOption3?: number,
}
type LensShapesSelfOptions = {
isHollywooded?: boolean,
offsetRadius?: number
};
type LensShapesOptions = LensShapesSelfOptions & OpticShapesOptions;
class LensShapes implements OpticShapes {
constructor( providedOptions?: LensShapesOptions ) {
// No error in this implementation
// const options = optionize<LensShapesOptions, LensShapesSelfOptions, OpticShapesOptions>( {
// isHollywooded: true,
// offsetRadius: 100
// }, providedOptions );
// Here notice that it will get mad at you because it expects all the optional parent options to be filled in here.
const options = optionize<LensShapesOptions, LensShapesOptions>( {
isHollywooded: true,
offsetRadius: 100
}, providedOptions );
}
} Now that there are parent options, using them in providedOptions (which by default passes them into the self options spot) will error out saying you need to set defaults for those parent options in this subtype. Again, still torn here, just trying to show the tradeoff, and wonder what the better default is. If we implement the way that @pixelzoom recommends, I think you will hit a red error more often, but perhaps that louder error may be helpful in reminding you to fill in self options to be narrower than providedOptions. @samreid do you have thoughts? |
Boy am I confused. I'm trying to get at a case where there are no ParentOptions, and you're converting it to a case that has ParentOptions. I still don't understand why that's relevant. And in your example: const options = optionize<LensShapesOptions, LensShapesOptions>( { Why would you use that form in this case? That seems just plain wrong wrong. There are no SelfOptions, and there are ParentOptions, so isn't this the correct form?: const options = optionize<LensShapesOptions, {}, OpticShapesOptions>( { |
I've been convinced enough to try it out. I'll let you know if things get complicated in any cases as I convert. |
… self options in usages, phetsims/phet-core#105
… self options in usages, phetsims/phet-core#105
… self options in usages, phetsims/phet-core#105
… self options in usages, phetsims/phet-core#105
So I think this is probably correct, but it is a behavior change that I think is worth a PSA about. @pixelzoom please review, and note the changes to Ratio and Proportion and Center and Spread in simple usages of optionize. Do you still agree with this change? |
Slack: Chris Malley [11:25 AM] Michael Kauzmann [11:25 AM] The second type arg determines what options require defaults in the first value argument object. (edited) I won't add it to dev meeting, we can keep discussing. |
@zepumph and I discussed my remaining questions via Zoom - thanks! I'm happy with where this is at, and understand what's going on. So closing. |
Using this regex, I realized how many usages there still are of specifying the second parameter type (the SelfOptions) by duplicating the first param:
For example: Reopening (note I'm not good at regex, I just found the "Repetition and Backreferences" section in https://www.regular-expressions.info/backref.html) |
… self options in usages, phetsims/phet-core#105
Can you help me understand or add a code comment why |
Yes. Added doc above. Basically @pixelzoom and I have been spending the last year trying to figure out what the best "default" optionize case is. For a while, we said that by default none of the keys needed defaults, thus SelfOptions was an empty object. Then we talked about/experimented with similar things in Parent options. By landing on SelfOptions by default taking the value of ProvidedOptions, the simple case is clearer, and doesn't require you to repeat the parameter twice (i.e. https://github.com/phetsims/wilder/blob/75388abc6e07721e91eca9ac7f7e3111cbb2d606/js/wilder/model/WilderOptionsPatterns.ts#L86-L103). Ready to close? |
Sounds great, thanks! Closing. |
In WilderOptionsPattern.ts:
This case keeps biting me, due to what feels like unnecessary duplication. Why does the second arg (SelfOptions) need to default to
{}
? Is there a reason why it can't default to the value of the first arg? So that the above is simply:The text was updated successfully, but these errors were encountered: