postgres icon indicating copy to clipboard operation
postgres copied to clipboard

What would be the right type to pass an object?

Open timonson opened this issue 2 years ago • 4 comments

Hello,

in my table "account" the column "contact" is of the type jsonb. Using the following interface, I get an TS Error:

error: TS2769 [ERROR]: No overload matches this call. Overload 1 of 2, '(first: TemplateStringsArray, ...rest: never): PendingQuery<Row[]>', gave the following error. Argument of type 'string' is not assignable to parameter of type 'never'. Overload 2 of 2, '(template: TemplateStringsArray, ...parameters: readonly ParameterOrFragment[]): PendingQuery<Row[]>', gave the following error. Argument of type 'object' is not assignable to parameter of type 'ParameterOrFragment'. return await sql`

I have two questions:

  1. Is it correct to pass an object like this for jsonb?
  2. If yes, what could I do to avoid the TS error?

Thank you very much!

interface AccountData {
  owner: string;
  email: string;
  contact: object;
  password: string;
}

async function insertAccount(
  { owner, email, contact, password }: AccountData,
) {
  return await sql`
    INSERT INTO public.account (owner, email, contact, hashed_password)
    VALUES (${owner}, ${email}, ${contact}, crypt(${password}, gen_salt('md5')))
  `;
}

const dataJane = {
  owner: "Jane Doe",
  email: "[email protected]",
  contact: { "phone": "12345" },
  password: "password123",
};

await insertAccount(dataJane);

timonson avatar Jun 29 '23 14:06 timonson

The query looks just right, and your object will be inserted correctly as jsonb.

Now for the typescript error, I don't know, and can't help since I don't use it :)

porsager avatar Jul 01 '23 19:07 porsager

If yes, what could I do to avoid the TS error?

Try casting contact to SerializableParameter<object> (see the type declaration, mind the never default). Like this:

…
  return await sql`
    INSERT INTO public.account (owner, email, contact, hashed_password)
    VALUES (${owner}, ${email}, ${contact as SerializableParameter<object>}, crypt(${password}, gen_salt('md5')))
  `;
…

atmin avatar Jul 06 '23 13:07 atmin

Is still throwing unfortunately:

async function insertRow(table: Table, input: any) {
  return table === "account"
    ? await sql`
    INSERT INTO ${sql(table)} (owner, email, contact, hashed_password)
    VALUES (${input.owner}, ${input.email}, ${input
      .contact as postgres.SerializableParameter<
        object
      >}, crypt(${input.password}, gen_salt('md5')))
    RETURNING *`
    : await sql`
    INSERT INTO ${sql(table)} ${sql(input)}
    RETURNING *`;
}

error: TS2769 [ERROR]: No overload matches this call. Argument of type '[Helper<"account", []>, any, any, SerializableParameter, any]' is not assignable to parameter of type 'never'. Overload 2 of 2, '(template: TemplateStringsArray, ...parameters: readonly ParameterOrFragment[]): PendingQuery<Row[]>', gave the following error. Argument of type 'SerializableParameter' is not assignable to parameter of type 'ParameterOrFragment'. Type 'object' is not assignable to type 'ParameterOrFragment'. ? await sql` ^

timonson avatar Jul 06 '23 16:07 timonson

I have the same problem and this works for me

import { SerializableParameter } from 'https://deno.land/x/[email protected]/types/index.d.ts';

// fields of cache table
//     key:  text
//     data: jsonb
async function add(key: string, data: unknown): Promise<boolean> {
    await this.sql`INSERT INTO cache ("key", "data") VALUES (${key}, ${data as SerializableParameter})`;

    // ... ...
}

koulerz avatar Aug 15 '23 18:08 koulerz