DEV Community

Cover image for How to Get Item by ID From Dynamodb Table with TypeScript?
Radzion Chachura
Radzion Chachura

Posted on • Originally published at radzion.com

How to Get Item by ID From Dynamodb Table with TypeScript?

Watch on YouTube

My app has a table with users, and I usually query just a handful of fields instead of the whole user object. That's why we have a second parameter called attributes. It is an array of user keys.

export async function getUserById<T extends (keyof User)[]>(
  id: string,
  attributes?: T
): Promise<Pick<User, T[number]> | undefined> {
  const { Item } = await documentClient
    .get(mergeParams(getUserItemParams(id), projectionExpression(attributes)))
    .promise()

  return Item as Pick<User, T[number]>
}
Enter fullscreen mode Exit fullscreen mode

To simplify interactions with DynamoDB, I have a handful of helpers.

projectionExpression converts an array to an object we can pass to the document client.

export const projectionExpression = (attributes?: string[]) => {
  if (!attributes) {
    return {}
  }

  const ProjectionExpression = attributes
    .map((attr) => `${attr.includes(".") ? "" : "#"}${attr}, `)
    .reduce((acc, str) => acc + str)
    .slice(0, -2)

  const attributesToExpression = attributes.filter(
    (attr) => !attr.includes(".")
  )

  const ExpressionAttributeNames = attributesToExpression.reduce<{
    [key: string]: string
  }>((acc, attr) => {
    acc["#" + attr] = attr
    return acc
  }, {})

  return attributesToExpression.length
    ? { ProjectionExpression, ExpressionAttributeNames }
    : { ProjectionExpression }
}
Enter fullscreen mode Exit fullscreen mode

I have a function like getUserItemParams for every table. It returns an object we need to get, update or delete an item.

export const getUserItemParams = (id: string) => ({
  TableName: tableName.users,
  Key: { id },
})
Enter fullscreen mode Exit fullscreen mode

Sometimes those helpers can return an object with a shared field ExpressionAttributeNames. To resolve such clashes, I use the mergeParams function.

export const mergeParams = (...params: any[]) =>
  params.reduce(
    (acc, param) =>
      Object.entries(param).reduce((acc, [key, value]) => {
        acc[key] = Array.isArray(value)
          ? [...acc[key], ...value]
          : typeof value === "object"
          ? { ...acc[key], ...value }
          : value
        return acc
      }, acc),
    {}
  )
Enter fullscreen mode Exit fullscreen mode

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay