Mattijs
Mattijs

Reputation: 3440

How to properly add return type to aws-sdk DynamoDb Send command

I am trying to get a generic type back as part of my OutputType when I do a DynamoDB Get using the new v3 aws-sdk.

My function looks like:

public async getItem<T>(data: GetItemCommandInput) {
  const command = new GetItemCommand({
    ...data
  });
  return await this.dbClient.send<GetItemCommand, T>(command);
}

Typescript is not happy with putting the T in the Send call. Looking at the typescript definition, it is pretty messy and I don't understand what they are doing. The first Type Send expects is of type ClientInput, and the second one of ClientOutput. Looking at the definition of ClientOutput my jaw just drops open:

ClientOutput extends MetadataBearer, ResolvedClientConfiguration extends SmithyResolvedConfiguration<HandlerOptions>> implements IClient<ClientInput, ClientOutput, ResolvedClientConfiguration>

....okay, they lost me.

Normally I would expect something like:

 await this.dbClient.send<GetItemCommandInput, T>(command);
or 
return await this.dbClient.send<GetItemCommandInput, GetItemCommandOutput<LegalAccount>>(command);

but GetItemCommandOutput doesn't allow for a generic.

Looking at the source typing I see:

export interface GetItemOutput {
    /**
     * <p>A map of attribute names to <code>AttributeValue</code> objects, as specified
     *             by <code>ProjectionExpression</code>.</p>
     */
    Item?: {
        [key: string]: AttributeValue;
    };

My whole point is that when I get the result of the query, I know that the Item inside the output is of type T. Did AWS just forget this or am I missing something. Docs are totally NOT helpful as expected :(

Upvotes: 5

Views: 4535

Answers (1)

Nemolo
Nemolo

Reputation: 80

i'm not sure that this can help you, i had a problem similar to yours and i finally found out this client.

Using this client i am able to perform query similarly to the old aws-sdk.

You have to set up the DynamoDB Client somewhat like this:

import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
const dynamoClient = new DynamoDBClient();
const ddbDocClient = DynamoDBDocumentClient.from(dynamoClient);

and your function could become something like this:

import { GetCommand, GetCommandInput } from "@aws-sdk/lib-dynamodb";
// ...
public async getItem<T>(data: GetCommandInput) {
  const command = new GetCommand({
    ...data
  });
  return await this.ddbDocClient.send(command) as Omit<GetCommandOutput, "Item"> & { Item: T };
}

As the documentation states:

The document client simplifies working with items in Amazon DynamoDB by abstracting away the notion of attribute values.

Then you can infer the type and expect it to work correctly.

Upvotes: 1

Related Questions