-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
Allow readonly array as parameter of .choices() #1667
Allow readonly array as parameter of .choices() #1667
Conversation
Without `readonly`, readonly arrays cannot be passed as parameters. Example: https://www.typescriptlang.org/play?#code/GYVwdgxgLglg9mABMAjACgIYCcsC5EDOUWMYA5gNoC6AlIgN4C+AUKJLAsgEyY75YBTDABMEAGwCehYqUq0GLZhARFE2LCkQBeRBQDkGPVQDcSlVDU4u23QaNqCiZWCKnW6dShqngPT9-deLC4A3yCQ4yA
I have been doing a bit of reading and still thinking about this. Just changing the type does allow passing a ReadonlyArray as parameter, and reflects the intent that the call itself will not change the array, and lets the caller prevent casual changes to their reference to the array. However, the Commander code effectively removes the readonly in the implementation, so it is weak! The array is stored in
choices(values) {
this.argChoices = values;
...
} The readonly could be honoured by taking a defensive copy of the parameter: choices(values) {
this.argChoices = Array.isArray(values) ? values.slice() : values;
...
} Reference: Related:
|
I don't think readonly can be used for parameters in JSDoc? |
Could you elaborate on why |
Hmm, good question. Probably not needed! I was being paranoid, and had in mind perhaps passing |
For interest, what is your use case? (Why do you have a readonly array of choices?) |
I use a library that provides a union type for valid options. The library doesn't provide an array for the valid options, so I created a readonly array in my own code that contains these options and type-checked the array against the union type provided by the library. |
lib/argument.js
Outdated
@@ -97,7 +97,7 @@ class Argument { | |||
*/ | |||
|
|||
choices(values) { | |||
this.argChoices = values; | |||
this.argChoices = values.slice(); | |||
this.parseArg = (arg, previous) => { | |||
if (!values.includes(arg)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The uses of values
in the parse function should be replaced with this.argChoices
now they may be different.
lib/option.js
Outdated
@@ -117,7 +117,7 @@ class Option { | |||
*/ | |||
|
|||
choices(values) { | |||
this.argChoices = values; | |||
this.argChoices = values.slice(); | |||
this.parseArg = (arg, previous) => { | |||
if (!values.includes(arg)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The uses of values
in the parse function should be replaced with this.argChoices
now they may be different.
I offered some tests in a PR back to the branch to check the parameter is actually treated as readonly at runtime. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this will be widely needed and requires taking a defensive copy of param, but do I like making the TypeScript API more usable (readonly) and safer (defensive copy).
Thumbs up from me. 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
Commander v9 has been released. |
Problem
Without
readonly
, readonly arrays cannot be passed as parameters.Example: https://www.typescriptlang.org/play?#code/GYVwdgxgLglg9mABMAjACgIYCcsC5EDOUWMYA5gNoC6AlIgN4C+AUKJLAsgEyY75YBTDABMEAGwCehYqUq0GLZhARFE2LCkQBeRBQDkGPVQDcSlVDU4u23QaNqCiZWCKnW6dShqngPT9-deLC4A3yCQ4yA
Solution
Add
readonly
in the TypeScript typings.ChangeLog
Allow readonly arrays as parameters of
.choices()
.