sam-goodwin / typesafe-dynamodb

TypeSafe type definitions for the AWS DynamoDB API
Apache License 2.0
205 stars 11 forks source link

QueryInput has no ExpressionAttributeValues argument #53

Closed kterui9019 closed 10 months ago

kterui9019 commented 10 months ago

Thanks for making a great tool.

Description

TypesafeQueryDocumentCommand does not accept the argument ExpressionAttributeValues.

import { TypeSafeQueryDocumentCommand } from 'typesafe-dynamodb/lib/query-document-command';

interface Person {
  email: string;
}

const queryperson = TypeSafeQueryDocumentCommand<Person>()

new queryperson({
  TableName: "",
  IndexName: "gsi2",
  KeyConditionExpression: `GSI2PK = :pk`,
  ExpressionAttributeValues: { // error
    ":pk": "email"
  }
})
Argument of type '{ TableName: string; IndexName: string; KeyConditionExpression: "GSI2PK = :pk"; ExpressionAttributeValues: { ":pk": string; }; }' is not assignable to parameter of type 'QueryInput<Person, "GSI2PK = :pk", string, string, "email", JsonFormat.Document>'.
  Object literal may only specify known properties, and 'ExpressionAttributeValues' does not exist in type 'QueryInput<Person, "GSI2PK = :pk", string, string, "email", JsonFormat.Document>'.ts(2345)

Indeed, there are no arguments in the QueryInput definition. node-modules/typesafe-dynamodb/lib/query.d.ts

export declare type QueryInput<Item extends object, KeyConditionExpression extends string | undefined, FilterExpression extends string | undefined, ProjectionExpression extends string | undefined, AttributesToGet extends keyof Item | undefined, Format extends JsonFormat> = Omit<DynamoDB.QueryInput, "AttributesToGet" | "KeyConditionExpression" | "FilterExpression" | "ExpressionAttributeNames" | "ExpressionAttributeValues"> & ExpressionAttributeNames<KeyConditionExpression> & ExpressionAttributeNames<FilterExpression> & ExpressionAttributeNames<ProjectionExpression> & ExpressionAttributeValues<KeyConditionExpression, Format> & ExpressionAttributeValues<FilterExpression, Format> & {
    KeyConditionExpression?: KeyConditionExpression;
    FilterExpression?: FilterExpression;
    ProjectionExpression?: ProjectionExpression;
    AttributesToGet?: AttributesToGet[];
};

There are definitions in src/query.ts, so it looks like the information is lost in the release.

src/query.ts

export type QueryInput<
  Item extends object,
  KeyConditionExpression extends string | undefined,
  FilterExpression extends string | undefined,
  ProjectionExpression extends string | undefined,
  AttributesToGet extends keyof Item | undefined,
  Format extends JsonFormat
> = Omit<
  DynamoDB.QueryInput,
  | "AttributesToGet"
  | "KeyConditionExpression"
  | "FilterExpression"
  | "ExpressionAttributeNames"
  | "ExpressionAttributeValues"
> &
  ExpressionAttributeNames<KeyConditionExpression> &
  ExpressionAttributeNames<FilterExpression> &
  ExpressionAttributeNames<ProjectionExpression> &
  ExpressionAttributeValues<KeyConditionExpression, Format> &
  ExpressionAttributeValues<FilterExpression, Format> & {
    KeyConditionExpression?: KeyConditionExpression;
    FilterExpression?: FilterExpression;
    ProjectionExpression?: ProjectionExpression;
    AttributesToGet?: AttributesToGet[];
  };

Tell me if you need anything.

sam-goodwin commented 10 months ago

I'm having a hard time re-producing this. It works correctly on my end. image

I created a repo trying to reproduce this. Maybe this will help? https://github.com/sam-goodwin/typesafe-dynamodb-repro

What is your typescript version and what does your tsconfig look like?

kterui9019 commented 10 months ago

Thanks for making the repo. I've tried that repo and have not seen any errors, so it's most likely a problem with my tsconfig.

Below is my tsconfig.

{
  "extends": "./node_modules/gts/tsconfig-google.json",
  "compilerOptions": {
    "module": "CommonJS",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "target": "ES2021",
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "incremental": true,
    "skipLibCheck": true,
    "strictNullChecks": false,
    "noImplicitAny": false,
    "strictBindCallApply": false,
    "forceConsistentCasingInFileNames": false,
    "noFallthroughCasesInSwitch": false,
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "rootDir": ".",
    "allowJs": true
  },
  "include": [
    "src/**/*.ts",
    "test/**/*.ts",
    "types/**/*.d.ts",
  ]
}
willsamu commented 6 months ago

I encountered the same issue. Sharing my solutio for other people.

These two compilerOptions need to be enabled in the tsconfig.json file:

In order to only apply these options partially to the folder where the library is being used, create a second tsconfig.json file under the respective path (e.g. for me src/services/Database) with the following contents (adapt filepath to main tsconfig file):

{
  "extends": "../../../tsconfig.json",
  "compilerOptions": {
    "strictNullChecks": true,
    "strictPropertyInitialization": true
  },
  "include": ["./**/*.ts"]
}
sam-goodwin commented 6 months ago

Thanks @willsamu. I wonder if there is anything else in your config that is required. Do you use the @tsconfig/node* base tsconfigs? I'd love to have a comprehensive recommendation for a tsconfig that we know works.

willsamu commented 5 months ago

Sure, this is my complete tsconfig, it's pretty basic:

{
  "extends": "./tsconfig.paths.json",
  "compilerOptions": {
    "allowJs": true,
    "lib": ["ESNext"],
    "moduleResolution": "node",
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "removeComments": true,
    "sourceMap": true,
    "target": "es2017",
    "outDir": "lib",
    "esModuleInterop": true,
    "resolveJsonModule": true
  },
  "include": ["src/**/*.ts"],
  "exclude": [
    "node_modules/**/*",
    ".serverless/**/*",
    ".webpack/**/*",
    "_warmup/**/*",
    ".vscode/**/*"
  ]
}

The ./tsconfig.paths.json just defines some paths for static imports.