-
-
Notifications
You must be signed in to change notification settings - Fork 140
Open
Description
Newer AWS services like bedrock-runtime are using union shapes in their API. Contrary to older services (like S3 or MediaConvert) that have a type
property containing an enum, and then additional properties used depending on the type, union shapes expect exactly 1 of their members to be filled.
Looking at official AWS SDKs for other languages (the official PHP SDK does not return typed responses and so cannot be used as comparison), here is how they represent it:
- JS defines a subtype for each member (naming it like
<shapeName>.<memberName>Member
) with that member defined with its type and all other members defined as optional properties with typenever
(which forbids having such properties in the object in typescript) and then uses a union type: https://github.com/aws/aws-sdk-js-v3/blob/b09a8f969ad6b2508e4d3de93089fe4498f57408/clients/client-bedrock-runtime/src/models/models_0.ts#L2351-L2382. They also expose aVisitor
interface with methods for each type, with avisit
function calling the right method of the visitor: https://github.com/aws/aws-sdk-js-v3/blob/b09a8f969ad6b2508e4d3de93089fe4498f57408/clients/client-bedrock-runtime/src/models/models_0.ts#L2544-L2569 (note that this Visitor interface seems to imply that adding a new member in the union would be a BC break) - Go defines an interface for the union shape, with implementations for each member (named
<shapeName>Member<memberName>
) that have aValue
field containing the value of the member: https://github.com/aws/aws-sdk-go-v2/blob/43445011355b4bb4226fa797c5fc141bbc1b793f/service/bedrockruntime/types/types.go#L127-L137 The serializer and deserializer take care of using the right structure for each kind of members. - the .NET SDK defines a class with a property for each member, which does not seem to enforce in the type system that only one member is set (maybe their generator does not have support for union shapes and generated it as a normal structure shape): https://github.com/aws/aws-sdk-net/blob/09201e894db71b5d536db6cb0975f361b85f1f52/sdk/src/Services/BedrockRuntime/Generated/Model/ContentBlock.cs
- the C++ SDK does something similar to the .NET SDK: https://github.com/aws/aws-sdk-cpp/blob/main/generated/src/aws-cpp-sdk-bedrock-runtime/source/model/ContentBlock.cpp
- the Ruby SDK does something weird. They have a ContentBlock class documenting that a single attribute should be set. And they also have subclasses that are used when deserializing (but that don't seem to limit the API in the type system): https://github.com/aws/aws-sdk-ruby/blob/934a6ad172c65754fa0975b48464c5499f368bd3/gems/aws-sdk-bedrockruntime/lib/aws-sdk-bedrockruntime/types.rb#L296-L298
- the Java SDK defines a class with getters for each members and a
type()
getter returning an enum identifying which member is relevant (inferred from which member is populated). That class has static factory methods for each member. See https://github.com/aws/aws-sdk-java-v2/blob/master/docs/design/core/tagged-unions/README.md#union-type-definition for an example in their design documentation (the generated code is not committed for the Java SDK) - The Kotlin SDK defines a sealed class for the union shape, with child classes for each member with a
value
field of the appropriate type. The base class hasas*
andas*OrNull
methods for each member that return the associatedvalue
if it is of the appropriate type and either throw or returnnull
when called on another type. See https://sdk.amazonaws.com/kotlin/api/latest/bedrockruntime/aws.sdk.kotlin.services.bedrockruntime.model/-content-block/index.html for an example
Metadata
Metadata
Assignees
Labels
No labels