Skip to content

Document arguments of various clients via proper detailed type definitions #3309

Open

Description

@Ocramius

Describe the feature

Context

Today, I wrote this:

private function instancesToDelete($tags) {
    return $this->rds->describeDBInstances(['Tags' => $tags])
}

This almost got me to delete production DBs by accident: Tags is completely ignored by RdsClient#describeDBInstances().

/cc @MarcoStagno @albertomolinari

The current API "documentation"

This proposal is about documenting clear array shapes for each API endpoint.

Currently, most API endpoints are documented as:

/**
 * @method \Aws\Result describeDBInstances(array $args = [])
 */

It suffices to say that this is absolutely useless rubbish.

The proposal

The generated API documentation should change, and become:

/**
 * @method \Aws\Result<list<array{
 *   foo: detailed-type-of-foo,
 *   bar: detailed-type-type-of-bar
 * }>> describeDBInstances(array{
 *   baz?: detailed-type-of-baz,
 *   taz?: detailed-rtype-of-taz
 * } $args = [])
 */

This is actually useful, self-documenting, and helpful for static analysis tooling (Psalm, PHPStan, Mago, Phan).

Use Case

This feature removes the need for jumping around web documentation when using the AWS SDK.

Proposed Solution

The code generator should convert documented types that are used under the hood into PHP types:

  • arrays
  • lists
  • non-empty-lists
  • string
  • non-empty-string
  • int
  • int<1, max>
  • etc.

Other Information

No response

Acknowledgements

  • I may be able to implement this feature request
  • This feature might incur a breaking change

SDK version used

3.379.0

Environment details (Version of PHP (php -v)? OS name and version, etc.)

PHP 8.4

Activity

  1. added
    feature-requestA feature should be added or improved.
    needs-triageThis issue or PR still needs to be triaged.
    on Jun 18, 2026
  2. changed the title [-]Document arguments of various clients via proper array shapes[/-] [+]Document arguments of various clients via proper detailed type definitions[/+] on Jun 18, 2026
  3. Ocramius commented on Jun 18, 2026

    @Ocramius
    Author

    An example of how asyncaws generates such API doc:

    Image

    This is really good DX, and prevents the mistake that almost led to production system damage today...

  4. self-assigned this
    on Jun 20, 2026
  5. stobrien89 commented on Jun 20, 2026

    @stobrien89
    Member

    Thanks for raising this, @Ocramius, and sorry for the close call.

    I understand the "jumping around web documentation" and find myself doing this often as a maintainer. The @method annotations were written when the SDK supported PHP 5.5, which is why they don't carry the kind of array shape info PHPStan or Psalm can use today. Luckily I think we're in a place now where we could do something about this.

    On the "tags ignored" issue- this is one I'd love to address in V3, but changing this behavior would not be backward-compatible. Something to think about for the future though 🔮

    If you, @MarcoStagno, and/or @albertomolinari can comment or add a reaction on #3017, that's where we're collecting feedback on future SDK direction/implementation and it'll help us prioritize.

    I'll leave this open as the tracking item for the array shape annotation work. No timeline yet, but will update when I know more. The async-aws example is a useful reference point.

  6. Ocramius commented on Jun 20, 2026

    @Ocramius
    Author

    Luckily I think we're in a place now where we could do something about this.

    Agreed 👍

    On the "tags ignored" issue- this is one I'd love to address in V3, but changing this behavior would not be backward-compatible. Something to think about for the future though 🔮

    I think we should stick to improving the generated docs: sealed array shapes suffice for this 👍

  7. stobrien89 commented on Jun 21, 2026

    @stobrien89
    Member

    Thanks for the comment on #3017. We have wanted to make some major updates in those areas for years now, and there's been some momentum behind it lately. Stay tuned 🔮

    For the docs improvement itself, I'm experimenting with a couple of approaches to get coverage in both IDEs and static analysis. Not sure we can have both because of magic@method limitations. I'll share more on this issue once I have something worth reviewing.

  8. stobrien89 commented on Jul 24, 2026

    @stobrien89
    Member

    @Ocramius,

    I've tried writing richer @method annotations and PHPStorm won't parse them- it doesn't seem the same format showed in your example above will work. What will work, however is keeping our existing @method annotations and adding an additional (psalm or) @phpstan-method annotation to document input. There doesn't appear to be autocomplete support in IDEs for this right now, but it's probably the best middle ground. Let me know what you think.

  9. Ocramius commented on Jul 24, 2026

    @Ocramius
    Author

    There doesn't appear to be autocomplete support in IDEs for this right now, but it's probably the best middle ground.

    Compared to what PHPStan/Psalm currently support, the IDE has always been lagging behind.

    An attempt could be also done with:

    /**
     * @phpstan-type SomeAlias1 array{foo: bar, baz: tab}
     * @phpstan-type SomeAlias2 array{tar: taz, war: waz}
     *
     * @method SomeAlias1 someMethod(SomeAlias2)
     */
  10. stobrien89 commented on Jul 25, 2026

    @stobrien89
    Member

    Very true, but it does seem like there are open feature requests to support autocomplete for these docblocks at least. Here is the current shape I'm working with:

     * @method \Aws\Result listObjectsV2(array $args = [])
     * @phpstan-method \Aws\Result listObjectsV2(array{
     *     Bucket?: string,
     *     Delimiter?: string,
     *     EncodingType?: 'url',
     *     MaxKeys?: int,
     *     Prefix?: string,
     *     ContinuationToken?: string,
     *     FetchOwner?: bool,
     *     StartAfter?: string,
     *     RequestPayer?: 'requester',
     *     ExpectedBucketOwner?: string,
     *     OptionalObjectAttributes?: list<'RestoreStatus'>,
     *     ...,
     * } $args = [])

    I have to be mindful of artifact size here- The size increase of this shape (adding to each client method) on the current SDK is roughly 12mb. For now I think we should only document input shapes this way.

  11. Ocramius commented on Jul 25, 2026

    @Ocramius
    Author

    Having this is tremendous value for downstream: I wouldn't mind the size much

  12. stobrien89 commented on Jul 25, 2026

    @stobrien89
    Member

    Opened #3331,

    Would appreciate input from others who reacted @drupol, @johnnoel, @hskrasek, @andrew-demb

  13. freddytqg commented on Sep 17, 2026

    @freddytqg

    Since 3.395.0 (#3331) the clients carry exact argument shapes. Thanks, big improvement. One gap makes them unusable for DynamoDB.

    The gap

    DynamoDbClient::putItem() now expects Item?: array<string, array{S?: string, N?: string, ...}>, but the canonical way to produce that value is still annotated as a plain @return array:

    // Aws\DynamoDb\Marshaler
    /** @return array Item formatted for DynamoDB. */
    public function marshalItem($item)

    PHPStan reads that as array<int|string, mixed>, which the new shape rejects:

    $client->putItem([
        'TableName' => $table,
        'Item' => $marshaler->marshalItem(['pk' => 'a', 'n' => 1]),
    ]);
    // 💡 Offset 'Item' does not accept type array<int|string, mixed>.  [argument.type]

    Hand-written shapes like ['Key' => ['pk' => ['S' => $id]]] pass fine. Only marshaled values fail, which is the path the DynamoDB docs point users to.

    Suggested fix

    Annotate the Marshaler with the shape the generator already emits:

    /**
     * @phpstan-type AttributeValue array{
     *     S?: string,
     *     N?: string,
     *     B?: string|resource|\Psr\Http\Message\StreamInterface,
     *     SS?: list<string>,
     *     NS?: list<string>,
     *     BS?: list<string|resource|\Psr\Http\Message\StreamInterface>,
     *     M?: array<string, array>,
     *     L?: list<array>,
     *     NULL?: bool,
     *     BOOL?: bool,
     * }
     */
    class Marshaler
    {
        /** @return array<string, AttributeValue> */
        public function marshalItem($item) {}
    
        /** @return AttributeValue */
        public function marshalValue($value) {}
    
        /** @return array<string, AttributeValue> */
        public function marshalJson($json) {}
    }

    unmarshalItem() / unmarshalValue() could take the same alias instead of bare array.


    SDK 3.395.3 · PHP 8.5 · PHPStan 2.2.14, level max

  14. stobrien89 commented on Oct 25, 2026

    @stobrien89
    Member

    @freddytqg,

    Thanks for catching this, and sorry we missed the comment. You’re right- the new DynamoDB client annotations expose a gap in the existing Marshaler return types.

    We should add an AttributeValue type alias and use it for the marshaling return types and unmarshaling inputs. I’ll follow up with a fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

feature-requestA feature should be added or improved.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions