Argument of type ‘(number | null)[]’ is not assignable to parameter of type ‘(err: Error, result: QueryResult) => void’

The latest “npm install @types/pg –save-dev” command changed the “@types/pg” Node.js module version in the package.json file from to “^8.11.4”.

Since that, the build of my TypeScript applications fail with the error message below, if the PostgreSQL .query function contains mixed “value” types, like this:

const query = "INSERT INTO ..."
const values = [string, number, stringArray, nullableValue]
const result = await conn.query(
      query,
      values
    );   

The error message is:

.. : error TS2769: No overload matches this call.
The last overload gave the following error.
Argument of type ‘(number | null)[]’ is not assignable to parameter of type ‘(err: Error, result: QueryResult) => void’.
Type ‘(number | null)[]’ provides no match for the signature ‘(err: Error, result: QueryResult): void’.

or

…: error TS2769: No overload matches this call.
The last overload gave the following error.
Argument of type ‘(string | number)[]’ is not assignable to parameter of type ‘(err: Error, result: QueryResult) => void’.

or

… : error TS2769: No overload matches this call.
The last overload gave the following error.
Argument of type ‘(string | number | null)[]’ is not assignable to parameter of type ‘(err: Error, result: QueryResult) => void’.
Type ‘(string | number | null)[]’ provides no match for the signature ‘(err: Error, result: QueryResult): void’.

Solution

I can see two solutions:

Make sure all elements of the array have the same data type

If possible, make sure the type of all value elements is the same, the simplest is to

  • convert numeric values to strings,
  • specify default values for “null” values,
  • convert string arrays to strings, or get the first element if only that has value.
const values = [number.toString(), canBeNullString || '' (canBeNullNumber || 0).toString(), stringArray[0]]

A better solution is to centralize the database access

If the database access is centralized in a function, and the values are passed in as “any” type, the TypeScript compiler will not reject it, because it does not iterate through all references of the function.

This is an example of the centralized PostgreSQL database call.
Install the required Node.js packages with

npm install typescript --save-dev
npm install @types/node --save-dev
npm install dotenv
npm install pg
npm install @types/pg --save-dev

The centralized PostgeSQL access file

// db.js

import * as dotenv from "dotenv";
dotenv.config()
import pg from 'pg'

// Create the reusable pool to the PostgreSQl database
// Read config values from environment variables
let conn = new pg.Pool({
  user: process.env.USER_NAME,
  password: process.env.PASSWORD,
  host: process.env.HOST,
  port: parseInt(process.env.PORT || "5432"),
  database: process.env.DATABASE,
});

// Call the "query" method of the pool to execute the text of the query with optional parameters
export const query = async (text: string, params: any) => {
  let res;

  try{

    if (params) {
      // There are parameters, send them with the query text
      res = await conn.query(text, params)
    } else {
      // There are no parameters
      res = await conn.query(text)
    }

  } catch (e) {
    // There is an error executing the query, log the error, the text of the query and the parameters
    console.log('error', e)
    console.log('query', text)
    console.log('params', params)
  }

  return res
}
  
export default query ;

Call the centralized function with

// selectData.ts

import * as conn from './db';

export async function selectData (id: string) {

  let result;
  let query;
  let values;

  try {
    
    // Build the query
    const baseQuery = "SELECT * FROM table";  

      query = baseQuery + ' ' + "WHERE id = $1";
      values = [id]

    // Query the database
    result = await conn.query(
        query
        , values
    );

    return result?.rows[0];

  } catch ( error ) {
    console.log("In selectData", error);
    console.log("result: ", result);
    console.log("query: ", query);
    console.log("values: ", values)
    return null;
    }
};

Leave a comment

Your email address will not be published. Required fields are marked *