Typescript and Knex

Viewed 1561

New to TypeScript. I'm developing a node application using Express, Postgresql and Knex and I'm a little confused in some areas as to when I should and shouldn't need to apply type definitions. I'm looking at other projects for some guidance, and I'm getting a bit confused as to how they are approaching when to use type definitions and when not to.

This is a version of code I saw. Why does this person define a return type Promise<Knex.Transaction> and then also uses type casting? Wouldn't you only need the return type for the function?

database/index.ts:

export default function startTransaction(): Promise<Knex.Transaction> {
 return new Promise((resolve, reject) => {
 return db
      .transaction((trx) => {
        return resolve(trx);
      })
      .catch(() => {
         reject('unable to complete transaction');
      });
  }) as Promise<Knex.Transaction>
}

Is this done correctly below? All I'd be using TypeScript with Knex is is for autocompletion aid for these queries?

model/company.ts:

interface Company {
 id: string;
 name: string;
 date_created: Date;
}

function getCompanies(trx: Knex.Transaction): Knex.QueryBuilder {
 return trx.table<Company>('company').returning('*');
}

This might be a dumb question, but for this controller below, you don't need to define' trx' type or 'companies' type because they are already defined in the model, right?

controller/company.ts:

const getCompanies: RequestHandler = async (req, res): Promise<void> => {
 const trx = await startTransaction();

 try {
     const companies = await Test.getCompanies(trx);
     await trx.commit();
     res.status(200).send(companies);
  } catch (error) {
     await trx.rollback();
     res.status(500).send(error);
  }
};

In general, when I am querying the database, do I also need to define the type the database returns back to me? I know when I am receiving client requests, I obviously need to ensure all those values are defined exactly as my database defines them. Thanks! Fundamental questions, but really helpful in me moving forward and understanding completely how I should approach this part of the project.

1 Answers

Why does this person define a return type Promise<Knex.Transaction> and then also uses type casting? Wouldn't you only need the return type for the function?

Typescript can infer the return type automatically. However, it's a good practice to add explicit return types. This is because Typescript doesn't always know what you want the return type to be. For example, you could be implementing a method to instantiate a concrete object, but you want the return type to be an interface, or parent class instead.

As for why the code uses typecast, it's because the code you copied from is wrong. If you look at the signature of knex.transaction, you will see it returns Promise<T>, and that is what resolve(trx) returns. So, yeah, don't use that code. It's wrong. :)

for this controller below, you don't need to define' trx' type or 'companies' type because they are already defined in the model, right?

Yes. The type is inferred for const trx and const company.

Related