- Notifications
You must be signed in to change notification settings - Fork 217
Refactor: Make defineString generic for better type-safety #1693
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
base: master
Are you sure you want to change the base?
Refactor: Make defineString generic for better type-safety #1693
Conversation
c4788a9 to 5e88ed1 Compare | runtimeValue(): string { | ||
| return process.env[this.name] || ""; | ||
| runtimeValue(): T { | ||
| return process.env[this.name] as T; |
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.
What happens when it's undefined? doesn't this cast undefined as T
| * Declare a string parameter. | ||
| * | ||
| * @param name The name of the environment variable to use to load the parameter. | ||
| * @param options Configuration options for the parameter. |
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 think the JSDoc needs updating?
Maybe something like this?
@returns A parameter whose `.value()` return type is narrowed based on the options provided. | value: T; | ||
| } | ||
| | ||
| /** |
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.
Can we add a comment here with a brief explanation of why NoInfer is needed here for future maintainers?
| /gemini |
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.
Code Review
This pull request introduces a great improvement by making defineString generic, which enhances type-safety when using select options. The use of NoInfer<T> is a good way to control type inference for the default value. However, I've found a critical issue in the implementation of StringParam.runtimeValue that could lead to runtime errors. My review includes a suggestion to fix this. Once that's addressed, this will be a solid refactoring.
| runtimeValue(): T { | ||
| return process.env[this.name] as T; | ||
| } |
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 implementation of runtimeValue has a potential issue. If process.env[this.name] is not set, it will be undefined, and undefined as T will return undefined. However, the return type T is constrained to string, so this violates the type contract and can lead to runtime errors when the value is used.
The previous implementation had a fallback to an empty string: process.env[this.name] || "". This behavior should be preserved to ensure a string is always returned, consistent with other parameter types that have zero-value fallbacks.
While returning "" might not be strictly correct if T is a union of literals that doesn't include "", it's a safer default than undefined and maintains consistency with the previous behavior.
| runtimeValue(): T { | |
| return process.env[this.name] as T; | |
| } | |
| runtimeValue(): T { | |
| return (process.env[this.name] || "") as T; | |
| } |
| It looks like you tried to invoke a command, but you didn't specify which one. Please use |
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.
Hi! Thanks for the contribution!
I think we'd probably want to add some test cases here -
- Test type narrowing works using select options - perhaps just type assertions?
- Test backward compatibility without select options
- Test runtime behavior when env var contains an invalid value?
- Test edge case when env var is undefined (see comment on the relevant code)
Description
The
defineStringfunction does not narrow the type when addinginput.select.options. This means we have to typecast in certain situations, even though we know what the types should be.Code sample
Limitations
defaultValueis provided with no options the value is still wide, rather than loose autocomplete