How to type node-postgres async query functions in TypeScript?

吃可爱长大的小学妹 提交于 2020-03-25 12:33:25

问题


I am fairly new to TypeScript and started to convert my existing server from ES6 to TypeScript. I am a bit lost and trying to figure out how to declare types for async functions. Here's a stub from the ES6 code:

// db.js
import { Pool } from 'pg';

const pool = new Pool({
  connectionString: 'process.env.DB_CONNECTION',
});

export default {

  query(text, params) {
    return new Promise((resolve, reject) => {
      try {
        const result = pool.query(text, params);
        return resolve(result);
      } catch (error) {
        return reject(error);
      }
    });
  },
};

// controller for a table
const Table = {
  getOne: async (id) => {
    return await db.query('SELECT * FROM table WHERE id=$1', [id]);
  },
}

This works fine and could be processed by consuming part in a try/catch block and it works whether the query returns a result or an error. Now how should I type these in typescript? I tried doing this:

import { Pool } from 'pg';

const pool = new Pool({
  connectionString: 'process.env.DB_CONNECTION',
});

export default {

  query(text: string, params: any[]) {
    return new Promise((resolve, reject) => {
      try {
        const result = pool.query(text, params);
        return resolve(result);
      } catch (error) {
        return reject(error);
      }
    });
  },
};

// controller
import { QueryResult } from 'pg';

const Table = {
  getOne: async (id: string) => {
    return await db.query('SELECT * FROM table WHERE id=$1', [id]) as QueryResult;
  },
}

Now, this compiles, but there are couple things I don't get. First, it is quite redundant to always cast these return types with 'as'. Shouldn't I be able to declare the return type somehow like this getOne: async (id: string): Promise<QueryResult> => {...}? Then, what would happen, if the promise rejected? That isn't a QueryResult type anymore afaik. I have tried to read the documentations about node-postgres and TypeScript function type declarations, but I am getting nowhere. How I should do these? Also probably I should start learning declaration files too.


回答1:


async functions implicitly return promises

example:

// Declare async function
async function getRandomNumberAsync(max: number): Promise<number> {
  return Math.floor(Math.random() * Math.floor(max));
}

// Call it (errors are handled with a try/catch)
try {
  const result = await getRandomNumberAsync(100);
  console.log(result);
} catch (e) {
  console.error("something went wrong");
}

async/await is just syntax sugar (behind the scenes, async/await use Promises). This code is basically equivalent to the above code

function getRandomNumberAsync(max: number): Promise<number> {
  return Promise.resolve(Math.floor(Math.random() * Math.floor(max)));
}

getRandomNumberAsync(100).then(result => {
  console.log(result);
}).catch(e => {
  console.error("something went wrong");
})

I can see that in your code, you're using return await which is redundant. There's even an eslint rule to prevent this

Your code should look something like this

const Table = {
  getOne: async (id: string): Promise<QueryResult> => {
    return db.query('SELECT * FROM table WHERE id=$1', [id]);
  },
}

// "getOne" should be called like this
try {
  const result = await Table.getOne("YOUR_ID");
  // handle result
} catch (e) {
  // handle error
}

unless you want to handle query errors inside getOne

It should look something like this

const Table = {
  getOne: async (id: string): Promise<QueryResult | string> => {
    try {
      return await db.query("SELECT * FROM table WHERE id=$1", [id]);
    } catch (e) {
      return "something went wrong";
    }
  },
}


来源:https://stackoverflow.com/questions/60355815/how-to-type-node-postgres-async-query-functions-in-typescript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!