amazon-web-servicesaws-lambdaamazon-dynamodbaws-sdkaws-sdk-js

DynamoDB get item TypeScript hell


Can anyone explain how to use GetItemInput type when calling DocumentClient.get ?

If I pass in an object of any type get works but if I try and strongly type the params object I get this error:

ValidationException: The provided key element does not match the schema

Here is my lambda function code where I pass the params as type any:

export const get: Handler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {

  console.log(event.pathParameters)
  if (!event.pathParameters) {
    throw Error("no path params")
  }

  const params: any = {
    Key: {
      id: event.pathParameters.id
    },
    TableName: table
  }

  console.log(params)
  try {
    const result: any = await dynamoDb.get(params).promise()
    return {
      body: JSON.stringify(result.Item),
      statusCode: result.$response.httpResponse.statusCode
    }

  } catch (error) {
    console.log(error)
    return {
      body: JSON.stringify({
        message: `Failed to get project with id: ${event.pathParameters!.id}`
      }),
      statusCode: 500
    }
  }
}

And here is my attempt to get it to work with type GetItemInput

export const get: Handler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {

  console.log(event.pathParameters)
  if (!event.pathParameters) {
    throw Error("no path params")
  }

  const params: GetItemInput = {
    Key: {
      "id": { S: event.pathParameters.id }
    },
    TableName: table
  }

  console.log(params)
  try {
    const result: any = await dynamoDb.get(params).promise()
    return {
      body: JSON.stringify(result.Item),
      statusCode: result.$response.httpResponse.statusCode
    }

  } catch (error) {
    console.log(error)
    return {
      body: JSON.stringify({
        message: `Failed to get project with id: ${event.pathParameters!.id}`
      }),
      statusCode: 500
    }
  }
}

If I leave the Key as before ala:

const params: GetItemInput = {
  Key: {
    id: event.pathParameters.id
  },
  TableName: table
}

Unsurprisingly I get a type error. But can't fathom how I can form my Key such that I dont get the ValidationException.

Note the id field is of type String in the DynamoDB.


Solution

  • I think you mix two different client definition files DynamoDB and DynamoDB.DocumentClient. While you're using the DynamoDB.DocumentClient client, at the same time you're using the interface DynamoDB.Types.GetItemInput from DynamoDB.

    You should use DynamoDB.DocumentClient.GetItemInput:

    import {DynamoDB} from 'aws-sdk';
    const dynamo = new DynamoDB.DocumentClient({apiVersion: '2012-08-10'});
    
    ...
    const params: DynamoDB.DocumentClient.GetItemInput = {
        TableName: table,
        Key: {
            id: event.pathParameters.id
        }
    };
    const result = await this.dynamo.get(params).promise();