Aws-sdk-js: DynamoDB DocumentClient typescript definitions seem to be incorrect

Created on 20 Nov 2018  路  5Comments  路  Source: aws/aws-sdk-js

Hi,
I am using the DocumentClient with typescript.

The type definitions seem to be incorrect:

  • The DocumentClient always returns JSON instead of an AttributeMap.

Here is the output of the type definitions document_client.d.ts for GetItem

export interface GetItemOutput {
    Item?: AttributeMap;
    ...
}
export type AttributeMap = {[key: string]: AttributeValue};
/**
   * A JavaScript object or native type.
   */
export type AttributeValue = any;

Note that the type definitions in dynamodb.d.ts of AttributeValue is different than in the document_client.d.ts (it also contains the same interfaces...):

export interface GetItemOutput {
   Item?: AttributeMap;
   ...
}
export interface AttributeValue {
    S?: StringAttributeValue;
   ...
}

As the documentation of the document client says,

A JavaScript object or native type.
Should I cast it to JSON?

In my package.json I use "aws-sdk": "^2.341.0", which includes the type definitions.

Here is the hacky code (JavaScript code copied from the DDB js tutorial) to reproduce the result as JSON (DocumentClient) vs a result with AttributeValues (DynamoDB):

var AWS = require('aws-sdk');
AWS.config.update({
  region: 'eu-west-1'
});
const tableName = 'table-name'
const KEY = 'abc'
var ddb = new AWS.DynamoDB({
  apiVersion: '2012-08-10'
});
var params = {
  RequestItems: {
    'table-name': {
      Keys: [{
        'key_id': {
          S: KEY
        }
      }]
    }
  }
};

ddb.batchGetItem(params, function (err, data) {
  if (err) {
    console.log("Error", err);
  } else {
    data.Responses[tableName].forEach(function (element, index, array) {
      console.log(element);
    });
  }
});
const docClient = new AWS.DynamoDB.DocumentClient();

const params2 = {
  ConsistentRead: true,
  RequestItems: {
    [tableName]: {
      Keys: [{
        "key_id": KEY
      }]
    },
  },
}
docClient.batchGet(params2, function (err, data) {
  if (err) {
    console.log("Error", err);
  } else {
    data.Responses[tableName].forEach(function (element, index, array) {
      console.log('----------------------------------------');
      console.log(' doc client output: ');
      console.log(element);
      console.log('----------------------------------------');
    });
  }
});

Clearly the doc client output does not contain the AttributeValue types (e.g. {"S": "foo"})

// raw DDB client
key_id: { S: 'abc' }

// DocumentClient output
key_id: 'abc'

It seems that the client is auto-generated.
https://github.com/aws/aws-sdk-js/blob/master/apis/dynamodb-2012-08-10.normal.json

Are the definitions up-to-date?

Thx. Simon

typings

Most helpful comment

Thanks for the fast reply.
The behaviour of the DocumentClient is correct.
The issue is about the type definitions: There are type definitions with overlapping types (which differ slightly).

I found out that the the issue is in how VS Code lets me navigate to the respective type definition files.
I was able to convince VS Code to use the correct type:

// import { GetItemOutput } from 'aws-sdk/clients/dynamodb';
import { DocumentClient } from 'aws-sdk/clients/dynamodb';

const resp: DocumentClient.GetItemOutput = ...

So this is not an issue of the type definitions.
It was my fault to rely on VS Code to point me to the correct type definition. I will close the issue.

All 5 comments

@simonmit

Thanks for opening this issue.

DocumentClient is intended to give you an unmarshalled response, allowing you to use JavaScript types in place of the DynamoDB AttributeValues.

I want to be sure I'm understanding the issue you have opened. Is the issue that the response is not what you are expecting? Or that it DocumentClient is returning responses that are as expected, but there is confusion that they are still called an AttributeValue?

Thanks for the fast reply.
The behaviour of the DocumentClient is correct.
The issue is about the type definitions: There are type definitions with overlapping types (which differ slightly).

I found out that the the issue is in how VS Code lets me navigate to the respective type definition files.
I was able to convince VS Code to use the correct type:

// import { GetItemOutput } from 'aws-sdk/clients/dynamodb';
import { DocumentClient } from 'aws-sdk/clients/dynamodb';

const resp: DocumentClient.GetItemOutput = ...

So this is not an issue of the type definitions.
It was my fault to rely on VS Code to point me to the correct type definition. I will close the issue.

@simonmit

Thanks for following up. That's helpful to understand regarding the VS Code behavior.

@srchase I just went down a little rabbit hole on this. Would be very helpful to document and note this in the d.ts files.

// These types...
import {
    DocumentClient,
    PutItemInput
} from 'aws-sdk/clients/dynamodb';

// Do not align with these types
import {
    DocumentClient as DocClient
} from 'aws-sdk/lib/dynamodb/document_client';

// DocClient.PutItemInput vs  PutItemInput

Having the top import path export the class but not do much to note the two different sets of interfaces is confusing. I had to fish for the ones in the DocumentClient namespace.

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.

Was this page helpful?
0 / 5 - 0 ratings