Shamoon
Shamoon

Reputation: 43639

How to define a return type for a DynamoDB get with TypeScript?

I have:

  let resItem: Schema

  resItem = await dynamoClient.get({
    TableName,
    Key: {
      uuid: request.body.uuid
    }
  }).promise()

but I get:

Type 'PromiseResult<GetItemOutput, AWSError>' is missing the following properties from type 'Schema': uuid, topics, phoneNumber, timezonets(2739)

Upvotes: 2

Views: 4470

Answers (3)

Guilherme
Guilherme

Reputation: 1021

Rather than calling dynamoClient.get() directly and trying to cast it to Schema, consider using libraries that simplify this process for you because the setup is done only once. I created this simple npm package dynamo-repo and I like advertising it because I think it solves a problem that no other one does without over-complicating it.

Let me show you how your code would look like:

import { DBItemBase} from "dynamo-repo";

interface Schema extends DBItemBase {
  uuid: string,
  topics: [],
  phoneNumber: string,
  timezonets: []
}

const resItem = await itemRepo.findItem({ uuid: "<uuid-value>" });

The const resItem will already be of type Schema

You only need to create the itemRepo once:

import { DynamoDBDocument } from "@aws-sdk/lib-dynamodb";
import { Schema } from "<path to your interface>";
import { Repo } from "dynamo-repo";

export class ItemRepo extends Repo<Schema, "uuid"> {
  constructor(ddbDocClient: DynamoDBDocument) {
   /*
    * ["uuid", "topics", "phoneNumber", "timezonets"] are the "Schema" attributes that are persisted in the table
    * PS: No need to worry about reserved words such as uuid!
    */
    super(ddbDocClient, TableName, ["uuid", "topics", "phoneNumber", "timezonets"], "uuid");
  }
}

Then instantiate it passing your DynamoDBDocument:

const itemRepo = new ItemRepo(dynamoClient);
  • It automatically handles special words - e.g. "uuid" etc.
  • It helps you keep your entities consistent, which is specially handy with indexes.
  • It simplifies dynamodb usage and also gives you other repository functions such as addItem(), updateItem(), updateExpressionItem(), searchItems(), deleteItem(), getAllItems() and batchGetItems() and they're all very intuitive and easy to use.

Upvotes: 1

Sigex
Sigex

Reputation: 2949

Here you go. This is known as the lazy way. As there is no way of knowing if the properties in the type ReturnType are actually there at runtime.

But the content is coming from a database call and we expect dynamoDB to work, that's why we don't unit test it.

export const get = async <ReturnType>(params: DynamoDB.DocumentClient.GetItemInput) => {
  try {
    const result = await dynamodb.get(params).promise();
    return {...result, Item: result.Item as ReturnType};
  } catch (error) {
    throw Error(error);
  }
};

Upvotes: -1

Ye Xiaoxing
Ye Xiaoxing

Reputation: 46

If you check the definition of GetItemOutput and the definition of PromiseResult you will see that the promise is returning an object of {Item, ConsumedCapacity, $response} but not the result only. So I think you should use PromiseResult as the type and use the Item attribute as your result.

Upvotes: 3

Related Questions