-
Notifications
You must be signed in to change notification settings - Fork 591
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
Remove | string
from enums
#4278
Comments
I have found a useful way to narrow enums to their modeled values, but it requires that you know the enum type. And it does not help type safety on inputs. function isModeledEnum<T>(enumType: { [s: string]: T }, v: T | string | undefined): v is T {
return Object.values(enumType).includes(v as any)
}
const {status} = await sfn.describeExecution({executionArn})
if (!isModeledEnum(ExecutionStatus, status) throw Error()
// status is now ExecutionStatus |
Hi @everett1992 , The reason why we are generating enums with the This is our measure of ensuring even if there's no enum types generated, customers could still have a meaningful way to handle enums. We have discussed this as a team and decided we are not going to change it. If you have some other thoughts I encourage you to write us internally so we can discuss this further. Thanks! |
The rust SDK generates enums for known values and an extra #[non_exhaustive]
pub enum ExecutionStatus {
Aborted,
Failed,
Running,
Succeeded,
TimedOut,
Unknown(UnknownVariantValue),
} type ExecutionStatus =
| Aborted,
| Failed,
| Running,
| Succeeded,
| TimedOut,
| Unknown<string>,
const res = await sfn.createStateMachine({
status: unknown("An unmodeled value for execution status"),
})
if (typeof res.status === 'string') {
// res.status is one of the modeled values
} else {
// we can access the unknown value
res.status.unknownValue
} |
FWIW, the TypeScript 5.2 Iteration Plan plans to alleviate this issue with microsoft/TypeScript#29729 |
microsoft/TypeScript#29729 only addresses autocomplete which is a small part of the issues
|
So @mattpocock shares an excellent workaround to allowing autocomplete with defined types, but also allow any generic string. He covers it here: https://www.youtube.com/live/8HoOxOd86M4?feature=share TLDR: Change // This will allow autocomplete for the types, AND still allow generics. 🤩
type Keys = "Active" | "Inactive" | "InProgress" | (string & {});
// Autocomplete shows "Active" | "Inactive" | "InProgress"
// But any generic string is allowed
const value: Keys = "Deleting" You can try it out over on the TS Playground, just go to the "" and hit Ctrl/Cmd+Space to see the autocomplete. |
Could you redirect this to the Smithy team either internally or in their repository: https://github.com/awslabs/smithy-typescript/tree/main? This is controlled in the file: In my opinion the For switches, a default seems to be acceptable even when all enum options are exhaustively checked. |
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs and link to relevant comments in this thread. |
Describe the feature
smithy-typescript and aws-sdk-js-v3 generate clients with
| string
for any enum type in the model. It breaks auto complete, which is annoying, and compile time type checks, which is unsafe.Use Case
TypeScript simplifies the documented 1 type from
ExecutionStatus | string
tostring
in error messages, auto complete, and type hints so it's hard to discover the generated enum values from an editor or commandline.The inclusion of
string
in output types prevents me from writing exhaustiveness checks that would fail at compile time if my code did not handle all cases. For example handling step functions execution status1.The inclusion of
string
in input types allows me to pass invalid values2I understand that smithy requires3 clients to allow unmodeled enum values but it does not require the current implementation.
Proposed Solution
My proposal is to replace all
| string
with a specific boxed valueUnmodeled<string>
. This is inspired by rust aws-sdk4, but obviously typescript doesn't support parameterized enums like they do.Instead of
status: ExecutionStatus | string
(which is simplified tostring
) we would havestatus: ExecutionStatus | Unmodeled<string>
. aws-sdk can ship aisModeled
typeguard which can narrow to only known values, or handle all unknown values.The sdk would still handle unknown enum values in respondes, but any value not modeled at build time would be wrapped with Unmodeled. Callers could still provide unmodeled values as long as they wrap the value, providing type safty for the majority of uses.
I think this pattern could be used beyond enums and replace
| undefined
and?
added to inputs. I do not recommend using this pattern for optional outputs #1613, where I prefer optional chaining.Acknowledgements
SDK version used
3.229.0
Environment details (OS name and version, etc.)
N/A
Footnotes
https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-sfn/interfaces/describeexecutioncommandoutput.html#status
https://github.com/aws/aws-sdk-js-v3/blob/main/codegen/sdk-codegen/aws-models/sfn.json#L3479 ↩ ↩2
https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-sfn/interfaces/createstatemachinecommandinput.html#type
https://github.com/aws/aws-sdk-js-v3/blob/main/codegen/sdk-codegen/aws-models/sfn.json#L5890 ↩
https://docs.rs/aws-sdk-sfn/latest/aws_sdk_sfn/model/enum.ExecutionStatus.html ↩
The text was updated successfully, but these errors were encountered: