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
feat: add InferredFlags type #473
Conversation
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.
approved but would love to have some assertion about it
* } | ||
* } | ||
*/ | ||
export type InferredFlags<T> = T extends FlagInput<infer F> ? F & { json: boolean | undefined; } : unknown |
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.
is there any way to test this? Maybe by building a test class and having a flags
property like your example, and then asserting things about its type?
What I'd like to do is prevent some future flag changes/refactoring/type fixing from breaking this feature.
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.
lgtm. Will approve once the sf-plugins-core stuff is updated.
Do you want to do the updates on sf-plugins-core or me?
public flags!: MyFlags | ||
|
||
public async run(): Promise<MyFlags> { | ||
const result = await this.parse(MyCommand) |
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 understand why the !
is there in here and in your example. It's kinda true...as long as people make
const {flags} = await this.parse(MyCommand)
(or whatever) their very first step in run
.
Is that worth adding to our linter? Are there situations where someone wouldn't want to parse the flags first (ex: checking some env, etc?) or not at all?
Otherwise, if they do the public flags!: MyFlags
but forget to parse (or try to use this.flags before parsing) the compiler won't warn them.
Or maybe the rule is "don't refer to the instance flags
prop if you haven't called the parse and assigned it?" ?
expectType<MyFlags>(this.flags) | ||
|
||
expectType<string>(this.flags.requiredGlobalFlag) | ||
expectNotType<undefined>(this.flags.requiredGlobalFlag) |
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.
this stuff is just way cool.
@@ -11,7 +11,8 @@ | |||
"strict": true, | |||
"target": "es2020", | |||
"lib": ["es2020"], | |||
"allowSyntheticDefaultImports": true | |||
"allowSyntheticDefaultImports": true, | |||
"noErrorTruncation": true, |
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.
oh, nice. How would you feel about this being in dev-config?
src/interfaces/parser.ts
Outdated
export type CustomOptionFlag<T, P = any> = FlagBase<T, string, P> & OptionFlagProps & { | ||
defaultHelp?: DefaultHelp<T>; | ||
input: string[]; | ||
} & ({ |
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.
very nice.
InferredFlags
toInterfaces
export. See details belowFlags.custom
to replaceFlags.build
. See details belowdefault
property always expecting a single item even ifmultiple
is set totrue
Potential Breaks
In order to switch the expected type of
default
based onmultiple
theInterfaces.OptionFlag
no longer has statically known members. Downstream, this means that any interface that extendsInterfaces.OptionFlag
will fail to compile. To fix this, you just need to switch to using atype
:Before
After
Additionally, the same change may cause custom flags that use
build
to fail compilation if you purposely override thedefault
. For example:This fails because the
default
type doesn't know what the value ofbaseProps.multiple
is. In order to fix this you need to add anif/else
like so:InferredFlags
Infer the flags that are returned by
Command.parse
. This is useful for when you want to assign the flags as a class property.Flags.custom
Custom flags built using
Flags.build
were not properly typed unless you specified a variety of function overloads (example).To replace that, we've introduced
Flags.custom
which allows us to define a custom with correct typing and no function overloading required:Before
After